diff --git a/resources/assets/stylesheets/scss/content_box.scss b/resources/assets/stylesheets/scss/content_box.scss index 1862ddf3e5634318d9a5c57e8db601d91851ff2a..3d88ff640efdfeb047da9bb1abe9240821718d2b 100644 --- a/resources/assets/stylesheets/scss/content_box.scss +++ b/resources/assets/stylesheets/scss/content_box.scss @@ -98,7 +98,7 @@ section.contentbox { max-height: 0; opacity: 0; overflow: auto; - transition: opacity 0.3s; + transition: opacity $transition-duration; } @@ -218,14 +218,14 @@ section.contentbox { max-height: 0; opacity: 0; overflow: auto; - transition: opacity 0.3s; + transition: opacity $transition-duration; } &.open { > p, > section, > footer, > div { max-height: none; opacity: 1; - transition: opacity 0.3s; + transition: opacity $transition-duration; } footer { diff --git a/resources/assets/stylesheets/scss/contentbar.scss b/resources/assets/stylesheets/scss/contentbar.scss index df2026f8c70a8d44139d7e5a59bf5ef7ba8d566f..a4e24afdc136b196f7b80df6455fee19cbe7af6e 100644 --- a/resources/assets/stylesheets/scss/contentbar.scss +++ b/resources/assets/stylesheets/scss/contentbar.scss @@ -129,28 +129,9 @@ body:not(.consuming_mode) { } body.consuming_mode { - #barBottomContainer, - #flex-header, - .secondary-navigation, - #barTopStudip, - #page_title_container { - max-height: 0px; - opacity: 0; - overflow: hidden; - } - - #layout_wrapper { - padding-top: 0px; - } - - #layout-sidebar { - margin-left: -280px; - opacity: 0; - } - .contentbar { margin-left: 10px; - margin-right: -0; + margin-right: 0; padding-left: 20px; padding-right: 20px; } diff --git a/resources/assets/stylesheets/scss/courseware.scss b/resources/assets/stylesheets/scss/courseware.scss index 3640c9ab2ccee02d007a881021b5046e1f1a1718..d006d6cc5137b9639aa76bc75f82f85588ccb9b9 100644 --- a/resources/assets/stylesheets/scss/courseware.scss +++ b/resources/assets/stylesheets/scss/courseware.scss @@ -1387,7 +1387,7 @@ label[for="cw-keypoint-color"] { padding-left: 1em; } > li.cw-tree-item { - margin: 4px 0; + margin: 4px 0; > .cw-tree-item-wrapper { border: none; > a.cw-tree-item-link { @@ -1421,7 +1421,7 @@ label[for="cw-keypoint-color"] { } } } - } + } } .cw-tree-item-link { @@ -5034,7 +5034,7 @@ text block end width: 40%; background: $white; padding: 20px; - transition: all 0.3s ease; + transition: all $transition-duration ease; h3 { padding: 15px; diff --git a/resources/assets/stylesheets/scss/forms.scss b/resources/assets/stylesheets/scss/forms.scss index a40a10a4dafbbc5ee54ecbc5e6f23f421d0a2651..e58a9c4b3e7dca152e167d8afbcb256804db2a57 100644 --- a/resources/assets/stylesheets/scss/forms.scss +++ b/resources/assets/stylesheets/scss/forms.scss @@ -48,7 +48,7 @@ form.default { padding: 5px; vertical-align: middle; width: 100%; - transition: all 0.3s ease-out; + transition: all $transition-duration ease-out; &:focus { border-color: $brand-color-dark; @@ -279,7 +279,7 @@ form.default { width: calc(100% - 2em); display: inline-block; - transition: all 0.3s ease-out; + transition: all $transition-duration ease-out; &:focus { border-color: $brand-color-dark; diff --git a/resources/assets/stylesheets/scss/header.scss b/resources/assets/stylesheets/scss/header.scss index bcd76b761b59118fb01b82ae322cc47afe663198..1f146cf456fece7d130c88b607683b2adbc1945a 100644 --- a/resources/assets/stylesheets/scss/header.scss +++ b/resources/assets/stylesheets/scss/header.scss @@ -17,10 +17,11 @@ flex-wrap: nowrap; justify-content: flex-start; + padding: 0 10px; transform: translate(0, 0) !important; // We need !important due to the horizontal scroll handler position: fixed; top: 0; - z-index: 10000; + z-index: 1000; } @@ -31,7 +32,7 @@ } #site-title { - padding: 0 $page-margin; + padding: 0 5px; } // Fix header covering relevant other areas diff --git a/resources/assets/stylesheets/scss/helpbar.scss b/resources/assets/stylesheets/scss/helpbar.scss index da0f0ca2fa656b58a20e7165c6d34e33a7ab74ea..ccb0333ed42b4b11a65c8eb2a930272346378194 100644 --- a/resources/assets/stylesheets/scss/helpbar.scss +++ b/resources/assets/stylesheets/scss/helpbar.scss @@ -15,7 +15,7 @@ $border-width: 4px; position: relative; top: 1px; min-width: 32px; - right: 17px; + right: 10px; float: right; diff --git a/resources/assets/stylesheets/scss/links.scss b/resources/assets/stylesheets/scss/links.scss index 34b37cd45bab1c1de0335020ff075db5e490cfa2..b5b9545e741617baeed2661995130eed67a8117d 100644 --- a/resources/assets/stylesheets/scss/links.scss +++ b/resources/assets/stylesheets/scss/links.scss @@ -13,7 +13,7 @@ a, a:link, a:visited { } a[href] { @media not prefers-reduced-motion { - transition: color 0.3s; + transition: color $transition-duration; } } a[disabled] { diff --git a/resources/assets/stylesheets/scss/raumzeit.scss b/resources/assets/stylesheets/scss/raumzeit.scss index fde8fd3ff0e989fab00371a279c35fbb7ba7c167..f5e904e4e43f82f2242e5ebf31666adf16ff3bf3 100644 --- a/resources/assets/stylesheets/scss/raumzeit.scss +++ b/resources/assets/stylesheets/scss/raumzeit.scss @@ -31,21 +31,21 @@ div.at_least_one_teacher { max-height: 0; opacity: 0; padding: 0; - transition: opacity 0.3s; + transition: opacity $transition-duration; } &:not(.open) header ~ * { max-height: 0; opacity: 0; overflow: auto; - transition: opacity 0.3s; + transition: opacity $transition-duration; } &.open { > p, > section, > footer, > div { max-height: none; opacity: 1; - transition: opacity 0.3s; + transition: opacity $transition-duration; } footer { diff --git a/resources/assets/stylesheets/scss/responsive.scss b/resources/assets/stylesheets/scss/responsive.scss index a57a3672daddc4223756b444382f9a217a972a4b..7610f960c5eea1cc96fc14ee44ca42508f7ff853 100644 --- a/resources/assets/stylesheets/scss/responsive.scss +++ b/resources/assets/stylesheets/scss/responsive.scss @@ -5,7 +5,7 @@ $header-bar-container-height: 40px; -$responsive-menu-width: 270px; +$responsive-menu-width: 1.5 * $sidebar-width; $sidebarIn: -15px; $sidebarOut: -330px; @@ -26,7 +26,7 @@ $sidebarOut: -330px; #non-responsive-toggle-fullscreen { margin-left: auto; - margin-right: 15px; + margin-right: 10px; position: relative; top: 2px; @@ -37,20 +37,19 @@ $sidebarOut: -330px; #responsive-menu { font-size: $font-size-base; - padding: 0 5px; + margin-top: 4px; z-index: 1002; .responsive-navigation-header { display: flex; - margin-top: 2px; - padding: 2px 0 5px; + padding: 2px 0; .menu-closed { cursor: pointer; transform: rotate(0deg); @media not prefers-reduced-motion { - transition: 0.5s ease-in-out; + transition: $transition-duration ease-in-out; } } @@ -59,17 +58,16 @@ $sidebarOut: -330px; transform: rotate(90deg); @media not prefers-reduced-motion { - transition: 0.5s ease-in-out; + transition: $transition-duration ease-in-out; } } } } -#responsive-navigation-button { +#responsive-navigation-button:not(.slide-enter-active):not(.slide-leave-active) { cursor: pointer; - left: 10px; - position: relative; + margin-left: -3px; } #responsive-navigation-items { @@ -92,7 +90,7 @@ $sidebarOut: -330px; width: $responsive-menu-width; @media not prefers-reduced-motion { - transition: all 0.5s ease-in-out; + transition: all $transition-duration ease-in-out; } header { @@ -168,8 +166,6 @@ $sidebarOut: -330px; &.navigation-up, &.navigation-current { - border-bottom: 2px solid $white; - .navigation-icon { img { padding-top: 0; @@ -187,7 +183,7 @@ $sidebarOut: -330px; } &.navigation-current { - background-color: $base-color-60; + background-color: $base-color-80; } a { @@ -292,7 +288,6 @@ $sidebarOut: -330px; > li.helpbar-container { float: unset; margin-top: 5px; - right: 30px; } } @@ -317,13 +312,13 @@ $sidebarOut: -330px; &.responsive-hide { @media not prefers-reduced-motion { - animation: slide-out 0.5s forwards; + animation: slide-out $transition-duration backwards; } } &.responsive-show { @media not prefers-reduced-motion { - animation: slide-in 0.5s forwards; + animation: slide-in $transition-duration forwards; } left: 15px; @@ -377,7 +372,6 @@ $sidebarOut: -330px; .contentbar-nav, .cw-ribbon-nav { width: auto; - margin-left: 5px; .contentbar-button { @@ -454,7 +448,20 @@ $sidebarOut: -330px; } .responsive-display:not(.fullscreen-mode) { + #top-bar { + padding: 0 3px; + } + + #index, + #login { + #top-bar { + padding: 0 20px; + } + } + #responsive-menu { + margin-left: -7px; + padding: 0 5px; width: calc(100% - 56px); } @@ -463,6 +470,15 @@ $sidebarOut: -330px; width: 100%; } + .contentbar-nav, + .cw-ribbon-nav { + margin-left: 3px; + } + + #toggle-sidebar { + margin-left: -10px; + } + #sidebar { height: 100%; position: fixed; @@ -506,13 +522,22 @@ $sidebarOut: -330px; #responsive-toggle-fullscreen { display: block; - right: 15px; + right: 30px; } .contentbar:not(#responsive-contentbar) { display: none; } + #responsive-contentbar { + padding-left: 15px; + + .contentbar-nav, + .cw-ribbon-nav { + margin-left: -8px; + } + } + #sidebar.responsive-hide { top: 110px; } @@ -529,9 +554,21 @@ $sidebarOut: -330px; #main-header, #sidebar, - #main-footer { + #main-footer, + #wikifooter { display: none; } + + #content { + height: 100vh; + position: fixed; + width: 100vw; + + .contentbar { + margin-right: 30px; + } + } + } html:not(.responsive-display):not(.fullscreen-mode) { diff --git a/resources/assets/stylesheets/scss/skiplinks.scss b/resources/assets/stylesheets/scss/skiplinks.scss index dd25f8bdde8dbbda4cc139de3cbd012b8a50c954..1737d841e8e11a6d5799a7cf181ead0214e8713a 100644 --- a/resources/assets/stylesheets/scss/skiplinks.scss +++ b/resources/assets/stylesheets/scss/skiplinks.scss @@ -38,6 +38,6 @@ button.skiplink { } @media not prefers-reduced-motion { - transition: color 0.3s; + transition: color $transition-duration; } } diff --git a/resources/assets/stylesheets/scss/tabs.scss b/resources/assets/stylesheets/scss/tabs.scss index 75e658f1952b0724d524d5d8f147fb6d3fa29aec..21731dba41047baacc4a86d3248afb4b50a2084e 100644 --- a/resources/assets/stylesheets/scss/tabs.scss +++ b/resources/assets/stylesheets/scss/tabs.scss @@ -57,7 +57,7 @@ div.clear float: left; display: block; - padding: 3px 8px 3px; + padding: 5px 8px; white-space: nowrap; height: 23px; } diff --git a/resources/assets/stylesheets/scss/variables.scss b/resources/assets/stylesheets/scss/variables.scss index 96b8cf62ea450c790bc10df1c9c565478b9430ee..1c2efacf9781340ffea84f2bd32ac2d602265b3e 100644 --- a/resources/assets/stylesheets/scss/variables.scss +++ b/resources/assets/stylesheets/scss/variables.scss @@ -40,6 +40,8 @@ $sidebar-border-width: 1px; $drag_and_drop_z_index: 1000; $drag_and_drop_border: 1px solid $base-color; +$transition-duration: .3s; + :root { // The special handling for -- as #{"--"} seems to be neccessary to make // scss evaluate the color variables diff --git a/resources/vue/components/courseware/CoursewareActionWidget.vue b/resources/vue/components/courseware/CoursewareActionWidget.vue index c6be07da16c307704f87a68f65c9e57b960e4679..8dbb7e48c915fe036075021839337796d3b372f2 100644 --- a/resources/vue/components/courseware/CoursewareActionWidget.vue +++ b/resources/vue/components/courseware/CoursewareActionWidget.vue @@ -9,7 +9,7 @@ </li> <li class="cw-action-widget-show-consume-mode"> <button @click="showConsumeMode"> - {{ $gettext('Vollbild einschalten') }} + {{ $gettext('Fokusmodus einschalten') }} </button> </li> <li v-if="canEdit && !blockedByAnotherUser" class="cw-action-widget-edit"> diff --git a/resources/vue/components/courseware/CoursewareRibbon.vue b/resources/vue/components/courseware/CoursewareRibbon.vue index 066a56fc69f2b2d0d3d91c47482132ed262251c5..c8bad6d21539c7bc42ed1132deb46900e7a4ec82 100644 --- a/resources/vue/components/courseware/CoursewareRibbon.vue +++ b/resources/vue/components/courseware/CoursewareRibbon.vue @@ -79,8 +79,8 @@ export default { stickyRibbon: false, textRibbon: { toolbar: this.$gettext('Inhaltsverzeichnis'), - fullscreen_on: this.$gettext('Vollbild einschalten'), - fullscreen_off: this.$gettext('Vollbild ausschalten'), + fullscreen_on: this.$gettext('Fokusmodus einschalten'), + fullscreen_off: this.$gettext('Fokusmodus ausschalten'), }, unfold: false, showTools: false, @@ -151,11 +151,11 @@ export default { } }, consumeMode(newState) { - this.$refs.consumeModeSwitch.focus(); + this.$refs.consumeModeSwitch?.focus(); if (newState) { - document.body.classList.add('consume'); + document.body.classList.add('consuming_mode'); } else { - document.body.classList.remove('consume'); + document.body.classList.remove('consuming_mode'); } } } diff --git a/resources/vue/components/responsive/ResponsiveContentBar.vue b/resources/vue/components/responsive/ResponsiveContentBar.vue index fa4146fd7190afdede87175949e5a123b07ea424..efcb160dc0fa6f68d0288de512b9d65bbd7bc5b0 100644 --- a/resources/vue/components/responsive/ResponsiveContentBar.vue +++ b/resources/vue/components/responsive/ResponsiveContentBar.vue @@ -100,7 +100,7 @@ export default { if (responsiveMode) { this.realContentbar.id = 'responsive-contentbar'; this.realContentbar.classList.add('contentbar'); - if (!this.realContentbar.querySelector('#toggle-sidebar-button')) { + if (!this.realContentbar.querySelector('#toggle-sidebar')) { this.realContentbar.querySelector(this.realContentbarIconContainer) .prepend(this.createSidebarIcon()); } @@ -114,7 +114,7 @@ export default { document.getElementById('responsive-contentbar-container').prepend(this.realContentbar); } else { this.realContentbar.id = 'contentbar'; - document.getElementById('toggle-sidebar-button').remove(); + document.getElementById('toggle-sidebar').remove(); if (this.realContentbarType === 'courseware') { this.realContentbar.classList.remove('contentbar'); @@ -134,7 +134,7 @@ export default { this.sidebarIconClasses.map(className => { button.classList.add(className); }); - button.id = 'toggle-sidebar-button'; + button.id = 'toggle-sidebar'; button.title = this.$gettext('Sidebar einblenden'); button.addEventListener('click', (event) => { button.classList.toggle('contentbar-button-sidebar-open'); diff --git a/resources/vue/components/responsive/ResponsiveNavigation.vue b/resources/vue/components/responsive/ResponsiveNavigation.vue index 18a10a158f4ae2ac2bef1eff92dab618c5dff217..09420217d959be64d71ff17a8b904f4f7a0f6bed 100644 --- a/resources/vue/components/responsive/ResponsiveNavigation.vue +++ b/resources/vue/components/responsive/ResponsiveNavigation.vue @@ -1,9 +1,8 @@ <template> - <div role="navigation"> + <div role="navigation" ref="container" v-if="menuNeeded"> <div class="responsive-navigation-header"> <transition name="slide" appear> - <button v-if="menuNeeded" - id="responsive-navigation-button" class="styleless" + <button id="responsive-navigation-button" class="styleless" :title="showMenu ? $gettext('Navigation schließen') : $gettext('Navigation öffnen')" aria-owns="responsive-navigation-items" @click.prevent="toggleMenu" @@ -19,7 +18,7 @@ :is-fullscreen="isFullscreen"></toggle-fullscreen> </div> <transition name="appear" appear> - <nav v-if="showMenu" id="responsive-navigation-items" class="responsive" ref="navigation" + <nav v-show="showMenu" id="responsive-navigation-items" class="responsive" ref="navigation" :aria-expanded="showMenu"> <header v-if="me.username !== 'nobody'"> <template v-if="!avatarMenuOpen"> @@ -335,9 +334,11 @@ export default { moveHelpbar() { let tag = 'div'; let target = '.tabs_wrapper'; + let before = '#non-responsive-toggle-fullscreen'; if (this.isFullscreen || this.isResponsive) { tag = 'li'; target = '#header-links ul'; + before = '#responsive-toggle-fullscreen'; } let helpBar = document.createElement(tag); @@ -354,7 +355,7 @@ export default { helpBar.appendChild(helpbarIcon); helpBar.appendChild(document.querySelector('div.helpbar')); helpBar.classList.add('helpbar-container'); - document.querySelector(target).appendChild(helpBar); + document.querySelector(target).insertBefore(helpBar, document.querySelector(before)); realHelpBar.remove(); } }, @@ -383,6 +384,7 @@ export default { STUDIP.Vue.emit('header-magic-enabled'); } else { this.headerMagic = false; + this.showMenu = false; STUDIP.Vue.emit('header-magic-disabled'); } break; @@ -433,6 +435,25 @@ export default { STUDIP.Cookie.set('responsive-navigation-hash', navigation.hash); return navigation.navigation; + }, + captureOutsideClick(target) { + if (target !== null) { + if (!this.$refs.container.contains(target)) { + this.toggleMenu(); + } + } + } + }, + watch: { + showMenu(newState) { + if (newState) { + // Click outside navigation menu should close it. + document.addEventListener('click', event => { + this.captureOutsideClick(event.target); + }, true); + } else { + document.removeEventListener('click', this.captureOutsideClick(null), true) + } } }, mounted() { @@ -456,19 +477,27 @@ export default { if (this.isResponsive || (this.isFullscreen && !this.isFocusMode)) { this.moveHelpbar(); } - }) + + }); + + // Pressing escape should close an open navigation. + window.addEventListener('keydown', event => { + if (event.key === 'Escape' && this.showMenu) { + this.toggleMenu(); + } + }); this.initialNavigation = this.currentNavigation; this.initialTitle = this.initialNavigation.title; STUDIP.Vue.on('responsive-navigation-move-to', path => { this.moveTo(path); - }) + }); // Listen to changes in fullscreen setting STUDIP.Vue.on('toggle-fullscreen', value => { this.setFullscreen(value); - }) + }); /* * Use an observer for html and body in order to check @@ -479,21 +508,21 @@ export default { const newValue = m.target.getAttribute(m.attributeName); this.onChangeViewMode(m.target.tagName, newValue); } - }) + }); // Observe <html> for class changes. this.observer.observe(html, { attributes: true, attributeOldValue : false, attributeFilter: ['class'] - }) + }); // Observe <body> for class changes. this.observer.observe(body, { attributes: true, attributeOldValue : false, attributeFilter: ['class'] - }) + }); // Observe courseware contentbar for consuming mode. STUDIP.Vue.on('courseware-ribbon-mounted', element => { @@ -502,7 +531,7 @@ export default { attributeOldValue : false, attributeFilter: ['class'] }) - }) + }); }, beforeDestroy() { this.observer.disconnect(); @@ -522,7 +551,7 @@ export default { .slide-enter-to, .slide-leave-from, .slide-leave { - margin-left: 0; + margin-left: -3px; } .slide-enter, diff --git a/templates/contentbar/contentbar.php b/templates/contentbar/contentbar.php index dcdeeb8bc0f7814be4865ca21e8fe3957bcd0b93..9183516ffc72f650656fe7478adbdb556e6854ef 100644 --- a/templates/contentbar/contentbar.php +++ b/templates/contentbar/contentbar.php @@ -24,7 +24,8 @@ <? endif ?> <div class="contentbar-button-wrapper contentbar-consuming-mode-wrapper"> - <button class="contentbar-button contentbar-button-zoom consuming_mode_trigger"></button> + <button class="contentbar-button contentbar-button-zoom consuming_mode_trigger" + title="<?= _('Fokusmodus ein-/ausschalten') ?>"></button> </div> <? if ($actionMenu) : ?> diff --git a/templates/tabs.php b/templates/tabs.php index cfdd550cecca06ad4b00cb2b79e3067326a2d35f..eb5999b719ccf43870f394d24b5e7d4fef76cf36 100644 --- a/templates/tabs.php +++ b/templates/tabs.php @@ -60,8 +60,8 @@ $ebene3 = []; <? endforeach ?> <? endif; ?> </ul> - <div id="non-responsive-toggle-fullscreen"></div> <? if (is_object($GLOBALS['perm']) && $GLOBALS['perm']->have_perm('autor')) : ?> <?= Helpbar::get()->render() ?> <? endif; ?> + <div id="non-responsive-toggle-fullscreen"></div> </div>