MDL-71456 theme_boost: drawers for blocks and the course index

This commit is contained in:
Bas Brands 2021-04-29 12:03:06 +02:00 committed by Ferran Recio
parent c357779722
commit 4fa713b0d4
17 changed files with 1525 additions and 57 deletions

View File

@ -255,6 +255,7 @@ $string['clickhelpiconformoreinfo'] = '... continues ... Click on the help icon
$string['clickhere'] = 'Click here ...';
$string['clicktohideshow'] = 'Click to expand or collapse';
$string['clicktochangeinbrackets'] = '{$a} (Click to change)';
$string['closedrawer'] = 'Close drawer';
$string['closewindow'] = 'Close this window';
$string['closebuttontitle'] = 'Close';
$string['collapse'] = 'Collapse';
@ -355,6 +356,7 @@ $string['coursehelpnewsitemsnumber'] = 'Number of recent announcements appearing
$string['coursehelpnumberweeks'] = 'Number of sections in the course (applies to certain course formats only).';
$string['coursehelpshowgrades'] = 'Enable the display of the gradebook. It does not prevent grades from being displayed within the individual activities.';
$string['coursehidden'] = 'This course is currently unavailable to students';
$string['courseindex'] = 'Course index';
$string['courseoverviewfiles'] = 'Course image';
$string['courseoverviewfilesext'] = 'Course image file extensions';
$string['courseoverviewfileslimit'] = 'Course image files limit';
@ -1528,6 +1530,8 @@ $string['numyears'] = '{$a} years';
$string['ok'] = 'OK';
$string['oldpassword'] = 'Current password';
$string['olduserdirectory'] = 'This is the OLD users directory, and is no longer needed. You may safely delete it. The files it contains have been copied to the NEW user directory.';
$string['opendrawerblocks'] = 'Open block drawer';
$string['opendrawerindex'] = 'Open course index drawer';
$string['optional'] = 'optional';
$string['options'] = 'options';
$string['order'] = 'Order';

2
theme/boost/amd/build/drawers.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,508 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Toggling the visibility of the secondary navigation on mobile.
*
* @module theme_boost/drawers
* @copyright 2021 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import ModalBackdrop from 'core/modal_backdrop';
import Templates from 'core/templates';
import * as Aria from 'core/aria';
import {dispatchEvent} from 'core/event_dispatcher';
import {debounce} from 'core/utils';
let backdropPromise = null;
const drawerMap = new Map();
/**
* Maximum sizes for breakpoints. This needs to correspond with Bootstrap
* Breakpoints
*
* @private
*/
const sizes = {
medium: 991,
large: 1400
};
/**
* Get the current body width.
*
* @returns {number} the current body width.
* @private
*/
const getCurrentWidth = () => {
const DomRect = document.body.getBoundingClientRect();
return DomRect.x + DomRect.width;
};
/**
* Check if the user uses a small size browser.
*
* @returns {boolean} true if the body is smaller than sizes.medium max size.
* @private
*/
const isSmall = () => {
const browserWidth = getCurrentWidth();
return browserWidth < sizes.medium;
};
/**
* Check if the user uses a medium size browser.
*
* @returns {boolean} true if the body is smaller than sizes.medium max size.
* @private
*/
const isMedium = () => {
const browserWidth = getCurrentWidth();
return (browserWidth >= sizes.medium) && (browserWidth < sizes.large);
};
/**
* Check if the user uses a large size browser.
*
* @returns {boolean} true if the body is smaller than sizes.large max size.
* @private
*/
const isLarge = () => {
const browserWidth = getCurrentWidth();
return browserWidth >= sizes.large;
};
/**
* Add a backdrop to the page.
*
* @returns {Promise} rendering of modal backdrop.
* @private
*/
const getBackdrop = () => {
if (!backdropPromise) {
backdropPromise = Templates.render('core/modal_backdrop', {})
.then(html => new ModalBackdrop(html))
.then(modalBackdrop => {
modalBackdrop.getAttachmentPoint().get(0).addEventListener('click', e => {
e.preventDefault();
Drawers.closeAllDrawers();
});
return modalBackdrop;
})
.catch();
}
return backdropPromise;
};
/**
* The Drawers class is used to control on-screen drawer elements.
*
* It handles opening, and closing of drawer elements, as well as more detailed behaviours such as closing a drawer when
* another drawer is opened, and supports closing a drawer when the screen is resized.
*
* Drawers are instantiated on page load, and can also be toggled lazily when toggling any drawer toggle, open button,
* or close button.
*
* A range of show and hide events are also dispatched as detailed in the class
* {@link module:theme_boost/drawers#eventTypes eventTypes} object.
*
* @example <caption>Standard usage</caption>
*
* // The module just needs to be included to add drawer support.
* import 'theme_boost/drawers';
*
* @example <caption>Manually open or close any drawer</caption>
*
* import Drawers from 'theme_boost/drawers';
*
* const myDrawer = Drawers.getDrawerInstanceForNode(document.querySelector('.myDrawerNode');
* myDrawer.closeDrawer();
*
* @example <caption>Listen to the before show event and cancel it</caption>
*
* import Drawers from 'theme_boost/drawers';
*
* document.addEventListener(Drawers.eventTypes.drawerShow, e => {
* // The drawer which will be shown.
* window.console.log(e.target);
*
* // The instance of the Drawers class for this drawer.
* window.console.log(e.detail.drawerInstance);
*
* // Prevent this drawer from being shown.
* e.preventDefault();
* });
*
* @example <caption>Listen to the shown event</caption>
*
* document.addEventListener(Drawers.eventTypes.drawerShown, e => {
* // The drawer which was shown.
* window.console.log(e.target);
*
* // The instance of the Drawers class for this drawer.
* window.console.log(e.detail.drawerInstance);
* });
*/
export default class Drawers {
/**
* The underlying HTMLElement which is controlled.
*/
drawerNode = null;
constructor(drawerNode) {
this.drawerNode = drawerNode;
if (this.drawerNode.classList.contains('show')) {
this.openDrawer();
} else {
Aria.hide(this.drawerNode);
}
drawerMap.set(drawerNode, this);
}
/**
* Whether the drawer is open.
*
* @returns {boolean}
*/
get isOpen() {
return this.drawerNode.classList.contains('show');
}
/**
* Whether the drawer should close when the window is resized
*
* @returns {boolean}
*/
get closeOnResize() {
return !!parseInt(this.drawerNode.dataset.closeOnResize);
}
/**
* The list of event types.
*
* @static
* @property {String} drawerShow See {@link event:theme_boost/drawers:show}
* @property {String} drawerShown See {@link event:theme_boost/drawers:shown}
* @property {String} drawerHide See {@link event:theme_boost/drawers:hide}
* @property {String} drawerHidden See {@link event:theme_boost/drawers:hidden}
*/
static eventTypes = {
/**
* An event triggered before a drawer is shown.
*
* @event theme_boost/drawers:show
* @type {CustomEvent}
* @property {HTMLElement} target The drawer that will be opened.
*/
drawerShow: 'theme_boost/drawers:show',
/**
* An event triggered after a drawer is shown.
*
* @event theme_boost/drawers:shown
* @type {CustomEvent}
* @property {HTMLElement} target The drawer that was be opened.
*/
drawerShown: 'theme_boost/drawers:shown',
/**
* An event triggered before a drawer is hidden.
*
* @event theme_boost/drawers:hide
* @type {CustomEvent}
* @property {HTMLElement} target The drawer that will be hidden.
*/
drawerHide: 'theme_boost/drawers:hide',
/**
* An event triggered after a drawer is hidden.
*
* @event theme_boost/drawers:hidden
* @type {CustomEvent}
* @property {HTMLElement} target The drawer that was be hidden.
*/
drawerHidden: 'theme_boost/drawers:hidden',
};
/**
* Get the drawer instance for the specified node
*
* @param {HTMLElement} drawerNode
* @returns {module:theme_boost/drawers}
*/
static getDrawerInstanceForNode(drawerNode) {
if (!drawerMap.has(drawerNode)) {
new Drawers(drawerNode);
}
return drawerMap.get(drawerNode);
}
/**
* Dispatch a drawer event.
*
* @param {string} eventname the event name
* @param {boolean} cancelable if the event is cancelable
* @returns {CustomEvent} the resulting custom event
*/
dispatchEvent(eventname, cancelable = false) {
return dispatchEvent(
eventname,
{
drawerInstance: this,
},
this.drawerNode,
{
cancelable,
}
);
}
/**
* Open the drawer.
*/
openDrawer() {
const showEvent = this.dispatchEvent(Drawers.eventTypes.drawerShow, true);
if (showEvent.defaultPrevented) {
return;
}
Aria.unhide(this.drawerNode);
this.drawerNode.classList.add('show');
const preference = this.drawerNode.dataset.preference;
if (preference) {
M.util.set_user_preference(preference, true);
}
const state = this.drawerNode.dataset.state;
if (state) {
const page = document.getElementById('page');
page.classList.add(state);
}
if (isSmall()) {
getBackdrop().then(backdrop => {
backdrop.show();
const pageWrapper = document.getElementById('page-wrapper');
pageWrapper.style.overflow = 'hidden';
return backdrop;
})
.catch();
}
const closeButton = this.drawerNode.querySelector('[data-toggle="drawers"][data-action="closedrawer"]');
closeButton.focus();
this.dispatchEvent(Drawers.eventTypes.drawerShown);
}
/**
* Close the drawer.
*/
closeDrawer() {
const hideEvent = this.dispatchEvent(Drawers.eventTypes.drawerHide, true);
if (hideEvent.defaultPrevented) {
return;
}
const preference = this.drawerNode.dataset.preference;
if (preference) {
M.util.set_user_preference(preference, false);
}
const state = this.drawerNode.dataset.state;
if (state) {
const page = document.getElementById('page');
page.classList.remove(state);
}
Aria.hide(this.drawerNode);
this.drawerNode.classList.remove('show');
getBackdrop().then(backdrop => {
backdrop.hide();
if (isMedium()) {
const pageWrapper = document.getElementById('page-wrapper');
pageWrapper.style.overflow = 'auto';
}
return backdrop;
})
.catch();
this.dispatchEvent(Drawers.eventTypes.drawerHidden);
}
/**
* Toggle visibility of the drawer.
*/
toggleVisibility() {
if (this.drawerNode.classList.contains('show')) {
this.closeDrawer();
} else {
this.openDrawer();
}
}
/**
* Close all drawers.
*/
static closeAllDrawers() {
drawerMap.forEach(drawerInstance => {
drawerInstance.closeDrawer();
});
}
/**
* Close all drawers except for the specified drawer.
*
* @param {module:theme_boost/drawers} comparisonInstance
*/
static closeOtherDrawers(comparisonInstance) {
drawerMap.forEach(drawerInstance => {
if (drawerInstance === comparisonInstance) {
return;
}
drawerInstance.closeDrawer();
});
}
}
/**
* Activate the scroller helper for the drawer layout.
*
* @private
*/
const scroller = () => {
const body = document.querySelector('body');
const drawerLayout = document.querySelector('#page.drawers');
drawerLayout.addEventListener("scroll", () => {
if (drawerLayout.scrollTop >= window.innerHeight) {
body.classList.add('scrolled');
} else {
body.classList.remove('scrolled');
}
});
};
/**
* Set the last used attribute for the last used toggle button for a drawer.
*
* @param {object} toggleButton The clicked button.
*/
const setLastUsedToggle = (toggleButton) => {
if (toggleButton.dataset.target) {
document.querySelectorAll('[data-toggle="drawers"][data-target="' + toggleButton.dataset.target + '"]')
.forEach(btn => {
btn.dataset.lastused = false;
});
toggleButton.dataset.lastused = true;
}
};
/**
* Set the focus to the last used button to open this drawer.
* @param {string} target The drawer target.
*/
const focusLastUsedToggle = (target) => {
const lastUsedButton = document.querySelector('[data-toggle="drawers"][data-target="' + target + '"][data-lastused="true"');
if (lastUsedButton) {
lastUsedButton.focus();
}
};
/**
* Register the event listeners for the drawer.
*
* @private
*/
const registerListeners = () => {
// Listen for show/hide events.
document.addEventListener('click', e => {
const toggleButton = e.target.closest('[data-toggle="drawers"][data-action="toggle"]');
if (toggleButton && toggleButton.dataset.target) {
e.preventDefault();
const targetDrawer = document.getElementById(toggleButton.dataset.target);
const drawerInstance = Drawers.getDrawerInstanceForNode(targetDrawer);
setLastUsedToggle(toggleButton);
drawerInstance.toggleVisibility();
}
const openDrawerButton = e.target.closest('[data-toggle="drawers"][data-action="opendrawer"]');
if (openDrawerButton && openDrawerButton.dataset.target) {
e.preventDefault();
const targetDrawer = document.getElementById(openDrawerButton.dataset.target);
const drawerInstance = Drawers.getDrawerInstanceForNode(targetDrawer);
setLastUsedToggle(toggleButton);
drawerInstance.openDrawer();
}
const closeDrawerButton = e.target.closest('[data-toggle="drawers"][data-action="closedrawer"]');
if (closeDrawerButton && closeDrawerButton.dataset.target) {
e.preventDefault();
const targetDrawer = document.getElementById(closeDrawerButton.dataset.target);
const drawerInstance = Drawers.getDrawerInstanceForNode(targetDrawer);
drawerInstance.closeDrawer();
focusLastUsedToggle(closeDrawerButton.dataset.target);
}
});
// Close drawer when another drawer opens.
document.addEventListener(Drawers.eventTypes.drawerShow, e => {
if (isLarge()) {
return;
}
Drawers.closeOtherDrawers(e.detail.drawerInstance);
});
const closeOnResizeListener = () => {
if (isSmall()) {
let anyOpen = false;
drawerMap.forEach(drawerInstance => {
if (drawerInstance.isOpen) {
if (drawerInstance.closeOnResize) {
drawerInstance.closeDrawer();
} else {
anyOpen = true;
}
}
});
if (anyOpen) {
getBackdrop().then(backdrop => backdrop.show()).catch();
}
} else {
getBackdrop().then(backdrop => backdrop.hide()).catch();
}
};
window.addEventListener('resize', debounce(closeOnResizeListener, 400));
};
scroller();
registerListeners();
const drawers = document.querySelectorAll('[data-region="fixed-drawer"]');
drawers.forEach(drawerNode => Drawers.getDrawerInstanceForNode(drawerNode));

View File

@ -49,7 +49,7 @@ $THEME->layouts = [
),
// Main course page.
'course' => array(
'file' => 'columns2.php',
'file' => 'drawers.php',
'regions' => array('side-pre'),
'defaultregion' => 'side-pre',
'options' => array('langmenu' => true),
@ -61,7 +61,7 @@ $THEME->layouts = [
),
// Part of course, typical for modules - default page layout if $cm specified in require_login().
'incourse' => array(
'file' => 'columns2.php',
'file' => 'drawers.php',
'regions' => array('side-pre'),
'defaultregion' => 'side-pre',
),

View File

@ -0,0 +1,89 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* A drawer based layout for the boost theme.
*
* @package theme_boost
* @copyright 2021 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/behat/lib.php');
user_preference_allow_ajax_update('drawer-open-nav', PARAM_ALPHA);
user_preference_allow_ajax_update('drawer-open-index', PARAM_BOOL);
user_preference_allow_ajax_update('drawer-open-block', PARAM_BOOL);
if (isloggedin()) {
$navdraweropen = (get_user_preferences('drawer-open-nav', 'true') == 'true');
$courseindexopen = (get_user_preferences('drawer-open-index') == true);
$blockdraweropen = (get_user_preferences('drawer-open-block') == true);
} else {
$navdraweropen = false;
$courseindexopen = false;
$blockdraweropen = false;
}
if (defined('BEHAT_SITE_RUNNING')) {
$blockdraweropen = true;
}
$extraclasses = ['uses-drawers'];
if ($navdraweropen) {
$extraclasses[] = 'drawer-open-left';
}
if ($courseindexopen) {
$extraclasses[] = 'drawer-open-index';
}
$blockshtml = $OUTPUT->blocks('side-pre');
$hasblocks = strpos($blockshtml, 'data-block=') !== false;
if (!$hasblocks) {
$blockdraweropen = false;
}
$courseindex = false;
if (!$courseindex) {
$courseindexopen = false;
}
$bodyattributes = $OUTPUT->body_attributes($extraclasses);
$buildregionmainsettings = !$PAGE->include_region_main_settings_in_header_actions();
// If the settings menu will be included in the header then don't add it here.
$regionmainsettingsmenu = $buildregionmainsettings ? $OUTPUT->region_main_settings_menu() : false;
$templatecontext = [
'sitename' => format_string($SITE->shortname, true, ['context' => context_course::instance(SITEID), "escape" => false]),
'output' => $OUTPUT,
'sidepreblocks' => $blockshtml,
'hasblocks' => $hasblocks,
'bodyattributes' => $bodyattributes,
'navdraweropen' => $navdraweropen,
'courseindexopen' => $courseindexopen,
'blockdraweropen' => $blockdraweropen,
'regionmainsettingsmenu' => $regionmainsettingsmenu,
'courseindex' => $courseindex,
'hasregionmainsettingsmenu' => !empty($regionmainsettingsmenu)
];
$nav = $PAGE->flatnav;
$templatecontext['flatnavigation'] = $nav;
$templatecontext['firstcollectionlabel'] = $nav->get_collectionlabel();
echo $OUTPUT->render_from_template('theme_boost/drawers', $templatecontext);

View File

@ -93,11 +93,19 @@ body.drawer-ease {
transition: margin-left 0.5s ease, margin-right 0.5s ease;
}
body.drawer-open-left {
body:not(.uses-drawers).drawer-open-left {
@include media-breakpoint-up(md) {
margin-left: $drawer-width;
}
}
body.drawer-open-left #page.drawers {
@include media-breakpoint-up(md) {
margin-left: $drawer-width;
padding-left: 1rem;
}
}
body.drawer-open-right {
@include media-breakpoint-up(md) {
margin-right: $drawer-width;
@ -112,7 +120,7 @@ $right-drawer-width: 320px;
@include transition(right .2s ease-in-out);
&.drawer {
z-index: $zindex-sticky;
z-index: $zindex-sticky + 1;
position: fixed;
top: $navbar-height;
right: 0;
@ -141,7 +149,7 @@ $right-drawer-width: 320px;
&.drawer {
top: 0;
height: 100%;
z-index: $zindex-fixed;
z-index: $zindex-fixed + 1;
}
}
body.drawer-open-left,
@ -155,3 +163,94 @@ $right-drawer-width: 320px;
box-shadow: 2px 2px 4px rgba(0, 0, 0, .08);
}
}
@mixin drawer() {
transition: left 0.2s ease, right 0.2s ease, top 0.2s ease, bottom 0.2s ease;
background-color: $body-bg;
z-index: $zindex-modal;
position: fixed;
height: 100vh;
top: 0;
}
@mixin drawertypes() {
&.drawer-left,
&.drawer-right {
width: $drawer-width;
max-width: $drawer-width;
}
&.drawer-right {
border-left: $border-width solid $border-color;
right: calc(-#{$drawer-width} + -10px);
@include box-shadow($box-shadow-drawer-right);
&.show {
right: 0;
}
}
&.drawer-left {
border-right: $border-width solid $border-color;
left: calc(-#{$drawer-width} + -10px);
@include box-shadow($box-shadow-drawer-left);
&.show {
left: 0;
}
}
&.drawer-bottom {
bottom: -110%;
&.show {
bottom: 0;
}
}
}
.drawer {
@include drawer();
@include drawertypes();
}
@include media-breakpoint-up(lg) {
.drawer {
z-index: 0;
}
}
.drawer-md,
.drawer-sm {
display: none;
}
@include media-breakpoint-down(md) {
.drawer-md {
display: block;
@include drawer();
@include drawertypes();
}
}
@include media-breakpoint-down(sm) {
.drawer-sm {
display: block;
@include drawer();
@include drawertypes();
}
}
.drawerheader {
padding: 0 0.75rem;
height: $navbar-height;
display: flex;
align-items: center;
border-bottom: $border-width solid $border-color;
.drawertoggle {
margin-left: auto;
}
}
.drawercontent {
height: calc(100% - #{$navbar-height});
display: flex;
flex-direction: column;
flex-wrap: nowrap;
overflow-y: auto;
padding: 0.5rem;
}

View File

@ -100,3 +100,23 @@ $iconsizes: map-merge((
.helplink .icon {
margin-left: 0.5rem;
}
.icons-collapse-expand {
.expanded-icon {
display: block;
}
.collapsed-icon {
display: none;
}
&.collapsed {
.expanded-icon {
display: none;
}
.collapsed-icon {
display: block;
}
}
}

View File

@ -32,3 +32,136 @@
}
}
}
#page.drawers {
margin-top: calc(#{$navbar-height} + 2rem);
padding-left: 10px;
padding-right: 10px;
.main-inner {
max-width: 100%;
width: 100%;
margin: 0 auto;
}
}
@include media-breakpoint-up(xl) {
.pagelayout-course {
#page.drawers .main-inner {
max-width: $course-content-maxwidth;
}
}
}
.drawer-left-toggle {
position: fixed;
top: calc(#{$navbar-height} + 0.5rem);
left: 0;
z-index: 2;
.btn {
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
padding: 0.375rem;
width: 2.5rem;
color: $white;
background-color: $primary;
.icon {
width: auto;
height: auto;
}
}
}
#page.drawers.show-drawer-left .drawer-left-toggle {
display: none;
}
.drawer-right-toggle {
position: fixed;
top: calc(#{$navbar-height} + 0.5rem);
right: 0;
z-index: 2;
.btn {
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
padding: 0.375rem;
width: 2.5rem;
color: $white;
background-color: $primary;
.icon {
width: auto;
height: auto;
}
}
}
#page.drawers.show-drawer-right .drawer-right-toggle {
display: none;
}
@include media-breakpoint-down(sm) {
//the scroll to top button
.drawer-toggles {
z-index: 100;
}
.drawer-right-toggle,
.drawer-left-toggle {
top: calc(100vh / 2 - 1rem);
}
#page.drawers.scroll-down {
.drawer-right-toggle {
transform: translateX(150%);
pointer-events: auto;
visibility: hidden;
}
.drawer-left-toggle {
transform: translateX(-150%);
pointer-events: auto;
visibility: hidden;
}
}
}
@include media-breakpoint-up(md) {
// Add some padding for the drawer toggle buttons
#page.drawers {
margin-top: $navbar-height;
padding-left: 3rem;
padding-right: 3rem;
}
}
@include media-breakpoint-up(lg) {
.drawer-left,
.drawer-right {
top: calc(#{$navbar-height} + 1px);
height: calc(100vh - #{$navbar-height});
}
#page.drawers {
overflow-y: auto;
transition: 0.2s;
height: calc(100vh - #{$navbar-height});
margin-top: $navbar-height;
left: 0;
right: 0;
&.show-drawer-left {
margin-left: $drawer-width;
margin-right: 0;
padding-left: 1rem;
}
&.show-drawer-right {
margin-left: 0;
margin-right: $drawer-width;
padding-right: 1rem;
}
&.show-drawer-left.show-drawer-right {
margin-left: $drawer-width;
margin-right: $drawer-width;
}
}
}
.drawercontrolbuttons {
margin-top: 92px;
.buttons {
z-index: 1;
}
}

View File

@ -32,19 +32,6 @@ select {
}
}
.path-mod-feedback .feedback_form .col-form-label {
display: block !important; /* stylelint-disable-line declaration-no-important */
}
// Feedback module
.path-mod-feedback .itemactions {
float: right;
}
.path-mod-feedback .itemhandle {
position: absolute;
right: 1rem;
}
// Forum module
.path-mod-forum .forumsearch {

View File

@ -23,3 +23,7 @@ $primary-nav-padding-y: ($spacer / 4) !default;
$primary-nav-padding-x: ($spacer / 2) !default;
$navbar-height: 50px !default;
$course-content-maxwidth: 800px;
$box-shadow-drawer-left: -0.25rem .25rem .8rem rgba($black, .025) !default;
$box-shadow-drawer-right: 0 .25rem .8rem rgba($black, .025) !default;

View File

@ -12042,6 +12042,18 @@ input[disabled] {
.helplink .icon {
margin-left: 0.5rem; }
.icons-collapse-expand .expanded-icon {
display: block; }
.icons-collapse-expand .collapsed-icon {
display: none; }
.icons-collapse-expand.collapsed .expanded-icon {
display: none; }
.icons-collapse-expand.collapsed .collapsed-icon {
display: block; }
/* admin.less */
.formtable tbody th {
font-weight: normal;
@ -14246,6 +14258,11 @@ body.drawer-ease {
body.drawer-open-left {
margin-left: 285px; } }
@media (min-width: 768px) {
body.drawer-open-left #page.drawers {
margin-left: 285px;
padding-left: 1rem; } }
@media (min-width: 768px) {
body.drawer-open-right {
margin-right: 285px; } }
@ -14258,7 +14275,7 @@ body.drawer-ease {
[data-region=right-hand-drawer] {
transition: none; } }
[data-region=right-hand-drawer].drawer {
z-index: 1020;
z-index: 1021;
position: fixed;
top: 50px;
right: 0;
@ -14282,7 +14299,7 @@ body.drawer-ease {
[data-region=right-hand-drawer].drawer {
top: 0;
height: 100%;
z-index: 1030; }
z-index: 1031; }
body.drawer-open-left,
body.drawer-open-right {
overflow: hidden; } }
@ -14290,6 +14307,110 @@ body.drawer-ease {
.dir-rtl [data-region=right-hand-drawer] {
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.08); }
.drawer {
transition: left 0.2s ease, right 0.2s ease, top 0.2s ease, bottom 0.2s ease;
background-color: #fff;
z-index: 1050;
position: fixed;
height: 100vh;
top: 0; }
.drawer.drawer-left, .drawer.drawer-right {
width: 285px;
max-width: 285px; }
.drawer.drawer-right {
border-left: 1px solid #dee2e6;
right: calc(-285px + -10px); }
.drawer.drawer-right.show {
right: 0; }
.drawer.drawer-left {
border-right: 1px solid #dee2e6;
left: calc(-285px + -10px); }
.drawer.drawer-left.show {
left: 0; }
.drawer.drawer-bottom {
bottom: -110%; }
.drawer.drawer-bottom.show {
bottom: 0; }
@media (min-width: 992px) {
.drawer {
z-index: 0; } }
.drawer-md,
.drawer-sm {
display: none; }
@media (max-width: 991.98px) {
.drawer-md {
display: block;
transition: left 0.2s ease, right 0.2s ease, top 0.2s ease, bottom 0.2s ease;
background-color: #fff;
z-index: 1050;
position: fixed;
height: 100vh;
top: 0; }
.drawer-md.drawer-left, .drawer-md.drawer-right {
width: 285px;
max-width: 285px; }
.drawer-md.drawer-right {
border-left: 1px solid #dee2e6;
right: calc(-285px + -10px); }
.drawer-md.drawer-right.show {
right: 0; }
.drawer-md.drawer-left {
border-right: 1px solid #dee2e6;
left: calc(-285px + -10px); }
.drawer-md.drawer-left.show {
left: 0; }
.drawer-md.drawer-bottom {
bottom: -110%; }
.drawer-md.drawer-bottom.show {
bottom: 0; } }
@media (max-width: 767.98px) {
.drawer-sm {
display: block;
transition: left 0.2s ease, right 0.2s ease, top 0.2s ease, bottom 0.2s ease;
background-color: #fff;
z-index: 1050;
position: fixed;
height: 100vh;
top: 0; }
.drawer-sm.drawer-left, .drawer-sm.drawer-right {
width: 285px;
max-width: 285px; }
.drawer-sm.drawer-right {
border-left: 1px solid #dee2e6;
right: calc(-285px + -10px); }
.drawer-sm.drawer-right.show {
right: 0; }
.drawer-sm.drawer-left {
border-right: 1px solid #dee2e6;
left: calc(-285px + -10px); }
.drawer-sm.drawer-left.show {
left: 0; }
.drawer-sm.drawer-bottom {
bottom: -110%; }
.drawer-sm.drawer-bottom.show {
bottom: 0; } }
.drawerheader {
padding: 0 0.75rem;
height: 50px;
display: flex;
align-items: center;
border-bottom: 1px solid #dee2e6; }
.drawerheader .drawertoggle {
margin-left: auto; }
.drawercontent {
height: calc(100% - 50px);
display: flex;
flex-direction: column;
flex-wrap: nowrap;
overflow-y: auto;
padding: 0.5rem; }
#page-my-index {
background-color: #f7f7f7; }
@ -16786,17 +16907,6 @@ select {
.path-mod-choice .choices .option label {
vertical-align: top; }
.path-mod-feedback .feedback_form .col-form-label {
display: block !important;
/* stylelint-disable-line declaration-no-important */ }
.path-mod-feedback .itemactions {
float: right; }
.path-mod-feedback .itemhandle {
position: absolute;
right: 1rem; }
.path-mod-forum .forumsearch input,
.path-mod-forum .forumsearch .helptooltip {
margin: 0 3px; }
@ -19352,6 +19462,109 @@ span[data-flexitour="container"][x-placement="right"], span[data-flexitour="cont
height: 1em;
font-size: 4em; }
#page.drawers {
margin-top: calc(50px + 2rem);
padding-left: 10px;
padding-right: 10px; }
#page.drawers .main-inner {
max-width: 100%;
width: 100%;
margin: 0 auto; }
@media (min-width: 1200px) {
.pagelayout-course #page.drawers .main-inner {
max-width: 800px; } }
.drawer-left-toggle {
position: fixed;
top: calc(50px + 0.5rem);
left: 0;
z-index: 2; }
.drawer-left-toggle .btn {
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
padding: 0.375rem;
width: 2.5rem;
color: #fff;
background-color: #0f6fc5; }
.drawer-left-toggle .btn .icon {
width: auto;
height: auto; }
#page.drawers.show-drawer-left .drawer-left-toggle {
display: none; }
.drawer-right-toggle {
position: fixed;
top: calc(50px + 0.5rem);
right: 0;
z-index: 2; }
.drawer-right-toggle .btn {
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
padding: 0.375rem;
width: 2.5rem;
color: #fff;
background-color: #0f6fc5; }
.drawer-right-toggle .btn .icon {
width: auto;
height: auto; }
#page.drawers.show-drawer-right .drawer-right-toggle {
display: none; }
@media (max-width: 767.98px) {
.drawer-toggles {
z-index: 100; }
.drawer-right-toggle,
.drawer-left-toggle {
top: calc(100vh / 2 - 1rem); }
#page.drawers.scroll-down .drawer-right-toggle {
transform: translateX(150%);
pointer-events: auto;
visibility: hidden; }
#page.drawers.scroll-down .drawer-left-toggle {
transform: translateX(-150%);
pointer-events: auto;
visibility: hidden; } }
@media (min-width: 768px) {
#page.drawers {
margin-top: 50px;
padding-left: 3rem;
padding-right: 3rem; } }
@media (min-width: 992px) {
.drawer-left,
.drawer-right {
top: calc(50px + 1px);
height: calc(100vh - 50px); }
#page.drawers {
overflow-y: auto;
transition: 0.2s;
height: calc(100vh - 50px);
margin-top: 50px;
left: 0;
right: 0; }
#page.drawers.show-drawer-left {
margin-left: 285px;
margin-right: 0;
padding-left: 1rem; }
#page.drawers.show-drawer-right {
margin-left: 0;
margin-right: 285px;
padding-right: 1rem; }
#page.drawers.show-drawer-left.show-drawer-right {
margin-left: 285px;
margin-right: 285px;
padding-left: 1rem;
padding-right: 1rem; } }
.drawercontrolbuttons {
margin-top: 92px; }
.drawercontrolbuttons .buttons {
z-index: 1; }
.form-control:-ms-input-placeholder {
color: #6c757d; }

View File

@ -90,6 +90,12 @@
</div>
</div>
{{{ output.standard_after_main_region_html }}}
<div id="goto-top-link">
{{! go to top is sticky to footer so needs to be sibling }}
<a class="btn btn-light" role="button" href="#" aria-label="{{#str}} totop, theme_boost {{/str}}">
{{#pix}} i/up, core{{/pix}}
</a>
</div>
{{> theme_boost/footer }}
</div>
@ -97,13 +103,8 @@
</html>
{{#js}}
M.util.js_pending('theme_boost/loader');
require(['theme_boost/loader'], function() {
require(['theme_boost/loader', 'theme_boost/drawer'], function(Loader, Drawer) {
Drawer.init();
M.util.js_complete('theme_boost/loader');
});
M.util.js_pending('theme_boost/drawer');
require(['theme_boost/drawer'], function(drawer) {
drawer.init();
M.util.js_complete('theme_boost/drawer');
});
{{/js}}

View File

@ -0,0 +1,48 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template theme_boost/drawer
Example context (json):
{
"drawerclasses": "drawer drawer-right",
"drawertrigger": "toggleblocks",
"drawerheading": "Blocks",
"drawerconent": "Content for the blocks region"
}
}}
<div {{!
}} class="{{$drawerclasses}}{{/drawerclasses}}"{{!
}} data-region="fixed-drawer"{{!
}} id="{{$id}}{{/id}}"{{!
}} data-preference="{{$drawerpreferencename}}{{/drawerpreferencename}}"{{!
}} data-state="{{$drawerstate}}{{/drawerstate}}"{{!
}} data-close-on-resize="{{$drawercloseonreize}}0{{/drawercloseonreize}}"{{!
}}>
<div class="drawerheader">
{{$drawerheading}}{{/drawerheading}}
<button class="btn drawertoggle icon-no-margin" data-toggle="drawers" data-action="closedrawer" data-target="{{$id}}{{/id}}">
{{#pix}}e/cancel, core, {{#str}}closedrawer, core{{/str}}{{/pix}}
</button>
</div>
<div class="drawercontent">
{{$drawercontent}}{{/drawercontent}}
</div>
</div>
{{#js}}
require(['theme_boost/drawers']);
{{/js}}

View File

@ -0,0 +1,152 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template theme_boost/drawers
Boost drawer template.
Context variables required for this template:
* sitename - The name of the site
* output - The core renderer for the page
* bodyattributes - attributes for the body tag as a string of html attributes
* sidepreblocks - HTML for the blocks
* hasblocks - true if there are blocks on this page
* courseindexopen - true if the nav drawer should be open on page load
* regionmainsettingsmenu - HTML for the region main settings menu
* hasregionmainsettingsmenu - There is a region main settings menu on this page.
Example context (json):
{
"sitename": "Moodle",
"output": {
"doctype": "<!DOCTYPE html>",
"page_title": "Test page",
"favicon": "favicon.ico",
"main_content": "<h1>Headings make html validators happier</h1>"
},
"bodyattributes":"",
"sidepreblocks": "<h2>Blocks html goes here</h2>",
"hasblocks":true,
"courseindexopen": true,
"navdraweropen": false,
"blockdraweropen": true,
"regionmainsettingsmenu": "",
"hasregionmainsettingsmenu": false
}
}}
{{> theme_boost/head }}
<body {{{ bodyattributes }}}>
{{> core/local/toast/wrapper}}
<div id="page-wrapper" class="d-print-block">
{{{ output.standard_top_of_body_html }}}
{{> theme_boost/navbar }}
{{> theme_boost/nav-drawer }}
{{#courseindex}}
{{< theme_boost/drawer }}
{{$id}}theme_boost-drawers-courseindex{{/id}}
{{$drawerclasses}}drawer drawer-left {{#courseindexopen}}show{{/courseindexopen}}{{/drawerclasses}}
{{$drawerheading}}
{{#str}} courseindex {{/str}}
{{/drawerheading}}
{{$drawercontent}}
{{{courseindex}}}
{{/drawercontent}}
{{$drawerpreferencename}}drawer-open-index{{/drawerpreferencename}}
{{$drawerstate}}show-drawer-left{{/drawerstate}}
{{/ theme_boost/drawer}}
{{/courseindex}}
{{#hasblocks}}
{{< theme_boost/drawer }}
{{$id}}theme_boost-drawers-blocks{{/id}}
{{$drawerclasses}}drawer drawer-right {{#blockdraweropen}}show{{/blockdraweropen}}{{/drawerclasses}}
{{$drawerheading}}
{{#str}} blocks {{/str}}
{{/drawerheading}}
{{$drawercontent}}
<section class="d-print-none" aria-label="{{#str}}blocks{{/str}}">
{{{ sidepreblocks }}}
</section>
{{/drawercontent}}
{{$drawerpreferencename}}drawer-open-block{{/drawerpreferencename}}
{{$drawerstate}}show-drawer-right{{/drawerstate}}
{{$drawercloseonresize}}1{{/drawercloseonresize}}
{{/ theme_boost/drawer}}
{{/hasblocks}}
<div id="page" data-region="mainpage" class="drawers {{#courseindexopen}}show-drawer-left{{/courseindexopen}} {{#blockdraweropen}}show-drawer-right{{/blockdraweropen}}">
<div id="topofscroll" class="main-inner">
<div class="drawer-toggles d-flex">
{{#courseindex}}
<div class="drawer-left-toggle open-nav">
<button class="btn icon-no-margin" data-toggle="drawers" data-action="toggle" data-target="theme_boost-drawers-courseindex">
<span class="sr-only">{{#str}}opendrawerindex, core{{/str}}</span>
{{#pix}}e/align_left, moodle, {{#str}}opendrawerindex, core{{/str}}{{/pix}}
</button>
</div>
{{/courseindex}}
{{#hasblocks}}
<div class="drawer-right-toggle ml-auto">
<button class="btn icon-no-margin" data-toggle="drawers" data-action="toggle" data-target="theme_boost-drawers-blocks">
<span class="sr-only">{{#str}}opendrawerblocks, core{{/str}}</span>
{{#pix}}i/categoryevent, moodle, {{#str}}opendrawerblocks, core{{/str}}{{/pix}}
</button>
</div>
{{/hasblocks}}
</div>
{{{ output.full_header }}}
<div id="page-content" class="pb-3 d-print-block">
<div id="region-main-box">
{{#hasregionmainsettingsmenu}}
<div id="region-main-settings-menu" class="d-print-none {{#hasblocks}}has-blocks{{/hasblocks}}">
<div> {{{ output.region_main_settings_menu }}} </div>
</div>
{{/hasregionmainsettingsmenu}}
<section id="region-main" aria-label="{{#str}}content{{/str}}">
{{#hasregionmainsettingsmenu}}
<div class="region_main_settings_menu_proxy"></div>
{{/hasregionmainsettingsmenu}}
{{{ output.course_content_header }}}
{{{ output.main_content }}}
{{{ output.activity_navigation }}}
{{{ output.course_content_footer }}}
</section>
</div>
</div>
<div id="goto-top-link">
<a class="btn btn-light" role="button" href="#topofscroll" aria-label="{{#str}} totop, theme_boost {{/str}}">
{{#pix}} i/up, core{{/pix}}
</a>
</div>
{{> theme_boost/footer }}
</div>
</div>
{{{ output.standard_after_main_region_html }}}
</div>
</body>
</html>
{{#js}}
M.util.js_pending('theme_boost/loader');
require(['theme_boost/loader', 'theme_boost/drawer'], function(Loader, Drawer) {
Drawer.init();
M.util.js_complete('theme_boost/loader');
});
{{/js}}

View File

@ -17,12 +17,6 @@
{{!
Page footer.
}}
<div id="goto-top-link">
{{! go to top is sticky to footer so needs to be sibling }}
<a class="btn btn-light" role="button" href="#" aria-label="{{#str}} totop, theme_boost {{/str}}">
{{#pix}} i/up, core{{/pix}}
</a>
</div>
<footer id="page-footer" class="py-3 bg-dark text-light">
<div class="container">
<div id="course-footer">{{{ output.course_footer }}}</div>

View File

@ -12263,6 +12263,18 @@ input[disabled] {
.helplink .icon {
margin-left: 0.5rem; }
.icons-collapse-expand .expanded-icon {
display: block; }
.icons-collapse-expand .collapsed-icon {
display: none; }
.icons-collapse-expand.collapsed .expanded-icon {
display: none; }
.icons-collapse-expand.collapsed .collapsed-icon {
display: block; }
/* admin.less */
.formtable tbody th {
font-weight: normal;
@ -14469,6 +14481,11 @@ body.drawer-ease {
body.drawer-open-left {
margin-left: 285px; } }
@media (min-width: 768px) {
body.drawer-open-left #page.drawers {
margin-left: 285px;
padding-left: 1rem; } }
@media (min-width: 768px) {
body.drawer-open-right {
margin-right: 285px; } }
@ -14481,7 +14498,7 @@ body.drawer-ease {
[data-region=right-hand-drawer] {
transition: none; } }
[data-region=right-hand-drawer].drawer {
z-index: 1020;
z-index: 1021;
position: fixed;
top: 50px;
right: 0;
@ -14505,7 +14522,7 @@ body.drawer-ease {
[data-region=right-hand-drawer].drawer {
top: 0;
height: 100%;
z-index: 1030; }
z-index: 1031; }
body.drawer-open-left,
body.drawer-open-right {
overflow: hidden; } }
@ -14513,6 +14530,110 @@ body.drawer-ease {
.dir-rtl [data-region=right-hand-drawer] {
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.08); }
.drawer {
transition: left 0.2s ease, right 0.2s ease, top 0.2s ease, bottom 0.2s ease;
background-color: #fff;
z-index: 1050;
position: fixed;
height: 100vh;
top: 0; }
.drawer.drawer-left, .drawer.drawer-right {
width: 285px;
max-width: 285px; }
.drawer.drawer-right {
border-left: 1px solid #dee2e6;
right: calc(-285px + -10px); }
.drawer.drawer-right.show {
right: 0; }
.drawer.drawer-left {
border-right: 1px solid #dee2e6;
left: calc(-285px + -10px); }
.drawer.drawer-left.show {
left: 0; }
.drawer.drawer-bottom {
bottom: -110%; }
.drawer.drawer-bottom.show {
bottom: 0; }
@media (min-width: 992px) {
.drawer {
z-index: 0; } }
.drawer-md,
.drawer-sm {
display: none; }
@media (max-width: 991.98px) {
.drawer-md {
display: block;
transition: left 0.2s ease, right 0.2s ease, top 0.2s ease, bottom 0.2s ease;
background-color: #fff;
z-index: 1050;
position: fixed;
height: 100vh;
top: 0; }
.drawer-md.drawer-left, .drawer-md.drawer-right {
width: 285px;
max-width: 285px; }
.drawer-md.drawer-right {
border-left: 1px solid #dee2e6;
right: calc(-285px + -10px); }
.drawer-md.drawer-right.show {
right: 0; }
.drawer-md.drawer-left {
border-right: 1px solid #dee2e6;
left: calc(-285px + -10px); }
.drawer-md.drawer-left.show {
left: 0; }
.drawer-md.drawer-bottom {
bottom: -110%; }
.drawer-md.drawer-bottom.show {
bottom: 0; } }
@media (max-width: 767.98px) {
.drawer-sm {
display: block;
transition: left 0.2s ease, right 0.2s ease, top 0.2s ease, bottom 0.2s ease;
background-color: #fff;
z-index: 1050;
position: fixed;
height: 100vh;
top: 0; }
.drawer-sm.drawer-left, .drawer-sm.drawer-right {
width: 285px;
max-width: 285px; }
.drawer-sm.drawer-right {
border-left: 1px solid #dee2e6;
right: calc(-285px + -10px); }
.drawer-sm.drawer-right.show {
right: 0; }
.drawer-sm.drawer-left {
border-right: 1px solid #dee2e6;
left: calc(-285px + -10px); }
.drawer-sm.drawer-left.show {
left: 0; }
.drawer-sm.drawer-bottom {
bottom: -110%; }
.drawer-sm.drawer-bottom.show {
bottom: 0; } }
.drawerheader {
padding: 0 0.75rem;
height: 50px;
display: flex;
align-items: center;
border-bottom: 1px solid #dee2e6; }
.drawerheader .drawertoggle {
margin-left: auto; }
.drawercontent {
height: calc(100% - 50px);
display: flex;
flex-direction: column;
flex-wrap: nowrap;
overflow-y: auto;
padding: 0.5rem; }
#page-my-index {
background-color: #f7f7f7; }
@ -17021,17 +17142,6 @@ select {
.path-mod-choice .choices .option label {
vertical-align: top; }
.path-mod-feedback .feedback_form .col-form-label {
display: block !important;
/* stylelint-disable-line declaration-no-important */ }
.path-mod-feedback .itemactions {
float: right; }
.path-mod-feedback .itemhandle {
position: absolute;
right: 1rem; }
.path-mod-forum .forumsearch input,
.path-mod-forum .forumsearch .helptooltip {
margin: 0 3px; }
@ -19542,6 +19652,109 @@ span[data-flexitour="container"][x-placement="right"], span[data-flexitour="cont
height: 1em;
font-size: 4em; }
#page.drawers {
margin-top: calc(50px + 2rem);
padding-left: 10px;
padding-right: 10px; }
#page.drawers .main-inner {
max-width: 100%;
width: 100%;
margin: 0 auto; }
@media (min-width: 1200px) {
.pagelayout-course #page.drawers .main-inner {
max-width: 800px; } }
.drawer-left-toggle {
position: fixed;
top: calc(50px + 0.5rem);
left: 0;
z-index: 2; }
.drawer-left-toggle .btn {
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
padding: 0.375rem;
width: 2.5rem;
color: #fff;
background-color: #0f6fc5; }
.drawer-left-toggle .btn .icon {
width: auto;
height: auto; }
#page.drawers.show-drawer-left .drawer-left-toggle {
display: none; }
.drawer-right-toggle {
position: fixed;
top: calc(50px + 0.5rem);
right: 0;
z-index: 2; }
.drawer-right-toggle .btn {
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
padding: 0.375rem;
width: 2.5rem;
color: #fff;
background-color: #0f6fc5; }
.drawer-right-toggle .btn .icon {
width: auto;
height: auto; }
#page.drawers.show-drawer-right .drawer-right-toggle {
display: none; }
@media (max-width: 767.98px) {
.drawer-toggles {
z-index: 100; }
.drawer-right-toggle,
.drawer-left-toggle {
top: calc(100vh / 2 - 1rem); }
#page.drawers.scroll-down .drawer-right-toggle {
transform: translateX(150%);
pointer-events: auto;
visibility: hidden; }
#page.drawers.scroll-down .drawer-left-toggle {
transform: translateX(-150%);
pointer-events: auto;
visibility: hidden; } }
@media (min-width: 768px) {
#page.drawers {
margin-top: 50px;
padding-left: 3rem;
padding-right: 3rem; } }
@media (min-width: 992px) {
.drawer-left,
.drawer-right {
top: calc(50px + 1px);
height: calc(100vh - 50px); }
#page.drawers {
overflow-y: auto;
transition: 0.2s;
height: calc(100vh - 50px);
margin-top: 50px;
left: 0;
right: 0; }
#page.drawers.show-drawer-left {
margin-left: 285px;
margin-right: 0;
padding-left: 1rem; }
#page.drawers.show-drawer-right {
margin-left: 0;
margin-right: 285px;
padding-right: 1rem; }
#page.drawers.show-drawer-left.show-drawer-right {
margin-left: 285px;
margin-right: 285px;
padding-left: 1rem;
padding-right: 1rem; } }
.drawercontrolbuttons {
margin-top: 92px; }
.drawercontrolbuttons .buttons {
z-index: 1; }
.form-control:-ms-input-placeholder {
color: #6e7377; }