diff --git a/resources/assets/js/components/index.js b/resources/assets/js/components/index.js index dd1d95a31..37e78e383 100644 --- a/resources/assets/js/components/index.js +++ b/resources/assets/js/components/index.js @@ -20,6 +20,7 @@ import shelfSort from "./shelf-sort"; import homepageControl from "./homepage-control"; import headerMobileToggle from "./header-mobile-toggle"; import listSortControl from "./list-sort-control"; +import triLayout from "./tri-layout"; const componentMapping = { @@ -45,6 +46,7 @@ const componentMapping = { 'homepage-control': homepageControl, 'header-mobile-toggle': headerMobileToggle, 'list-sort-control': listSortControl, + 'tri-layout': triLayout, }; window.components = {}; diff --git a/resources/assets/js/components/tri-layout.js b/resources/assets/js/components/tri-layout.js new file mode 100644 index 000000000..cb6e02fcc --- /dev/null +++ b/resources/assets/js/components/tri-layout.js @@ -0,0 +1,81 @@ + +class TriLayout { + + constructor(elem) { + this.elem = elem; + this.middle = elem.querySelector('.tri-layout-middle'); + this.right = elem.querySelector('.tri-layout-right'); + this.left = elem.querySelector('.tri-layout-left'); + + this.lastLayoutType = 'none'; + this.onDestroy = null; + + + this.updateLayout(); + window.addEventListener('resize', event => { + this.updateLayout(); + }); + } + + updateLayout() { + const newLayout = (window.innerWidth <= 1000) ? 'mobile' : 'desktop'; + if (newLayout === this.lastLayoutType) return; + + if (this.onDestroy) { + this.onDestroy(); + this.onDestroy = null; + } + + if (newLayout === 'desktop') { + this.setupDesktop(); + } else { + this.setupMobile(); + } + + this.lastLayoutType = newLayout; + } + + setupMobile() { + const mobileSidebarClickBound = this.mobileSidebarClick.bind(this); + const mobileContentClickBound = this.mobileContentClick.bind(this); + this.left.addEventListener('click', mobileSidebarClickBound); + this.right.addEventListener('click', mobileSidebarClickBound); + this.middle.addEventListener('click', mobileContentClickBound); + + this.onDestroy = () => { + this.left.removeEventListener('click', mobileSidebarClickBound); + this.right.removeEventListener('click', mobileSidebarClickBound); + this.middle.removeEventListener('click', mobileContentClickBound); + } + } + + setupDesktop() { + // TODO + } + + /** + * Slide the main content back into view if clicked and + * currently slid out of view. + * @param event + */ + mobileContentClick(event) { + this.elem.classList.remove('mobile-open'); + } + + /** + * On sidebar click, Show the content by sliding the main content out. + * @param event + */ + mobileSidebarClick(event) { + if (this.elem.classList.contains('mobile-open')) { + this.elem.classList.remove('mobile-open'); + } else { + event.preventDefault(); + event.stopPropagation(); + this.elem.classList.add('mobile-open'); + } + } + +} + +export default TriLayout; \ No newline at end of file diff --git a/resources/assets/sass/_grid.scss b/resources/assets/sass/_grid.scss index cde2dfcca..8917889d4 100644 --- a/resources/assets/sass/_grid.scss +++ b/resources/assets/sass/_grid.scss @@ -50,107 +50,83 @@ body.flexbox { flex: 1; } -.flex.sidebar { - flex: 1; - background-color: #F2F2F2; - max-width: 420px; - min-height: 90vh; - section { - margin: $-m; - } -} -.flex.sidebar + .flex { - flex: 3; - max-width: 100%; -} -.flex.sidebar + .flex .content-wrap { - padding: $-l $-xxl; - margin-left: auto; - margin-right: auto; - margin-bottom: $-xl; - overflow: auto; - &.thin { - width: 940px; - max-width: 100%; - } -} -.flex.sidebar .sidebar-toggle { - display: none; -} -@include smaller-than($xl) { - body.sidebar-layout { - padding-left: 30px; +.tri-layout-container { + display: grid; + grid-template-columns: 1fr minmax(auto, 940px) 1fr; + grid-template-areas: "a b c"; + grid-column-gap: $-xl; + padding-right: $-xl; + padding-left: $-xl; + .tri-layout-right { + grid-area: c; } - .flex.sidebar { - position: fixed; - top: 0; - left: 0; - bottom: 0; - z-index: 100; - padding-right: 30px; - width: 360px; - box-shadow: none; - transform: translate3d(-330px, 0, 0); - transition: transform ease-in-out 120ms; - display: flex; - flex-direction: column; + .tri-layout-left { + grid-area: a; } - .flex.sidebar.open { - box-shadow: 1px 2px 2px 1px rgba(0,0,0,.10); - transform: translate3d(0, 0, 0); - .sidebar-toggle i { - transform: rotate(180deg); + .tri-layout-middle { + grid-area: b; + } + .content-wrap.card { + padding: $-l $-xxl; + margin-left: auto; + margin-right: auto; + margin-bottom: $-xl; + overflow: auto; + &.thin { + width: 940px; + max-width: 100%; } } - .flex.sidebar .sidebar-toggle { - display: block; - position: absolute; - opacity: 0.9; - right: 0; - top: 0; - bottom: 0; - width: 30px; - fill: #666; - font-size: 20px; - vertical-align: middle; - text-align: center; - border: 1px solid #DDD; - border-top: 1px solid #BBB; - padding-top: $-m; - cursor: pointer; - svg { - opacity: 0.5; - transition: all ease-in-out 120ms; - margin: 0; - } - &:hover i { - opacity: 1; - } - } - .sidebar .scroll-body { - flex: 1; - overflow-y: scroll; - } - #sidebar .scroll-body.fixed { - width: auto !important; - } } - -@include larger-than($xl) { - #sidebar .scroll-body.fixed { - z-index: 5; - position: fixed; - top: 0; - padding-top: $-m; - width: 30%; - left: 0; - height: 100%; - overflow-y: auto; - -ms-overflow-style: none; - //background-color: $primary-faded; - border-left: 1px solid #DDD; - &::-webkit-scrollbar { width: 0 !important } +@include smaller-than($xxl) { + .tri-layout-container { + grid-template-areas: "c b b" + "a b b"; + grid-template-columns: 1fr 3fr; + grid-template-rows: max-content min-content; + .content-wrap.card { + padding: $-l $-l; + } + } +} +@include smaller-than($l) { + .tri-layout-container { + grid-template-areas: none; + grid-template-columns: 10% 90%; + grid-column-gap: 0; + padding-right: $-l; + padding-left: $-l; + .tri-layout-right, .tri-layout-left { + opacity: 0.6; + z-index: 0; + } + .tri-layout-left > *, .tri-layout-right > * { + pointer-events: none; + } + .tri-layout-right, .tri-layout-left, .tri-layout-middle { + grid-area: none; + grid-column: 1/3; + grid-row: 1; + } + .tri-layout-middle { + grid-row: 1/3; + grid-column: 2/3; + z-index: 1; + transition: transform ease-in-out 240ms; + } + .tri-layout-left { + grid-row: 2; + } + &.mobile-open { + overflow: hidden; + .tri-layout-middle { + transform: translateX(90%); + } + .tri-layout-right > *, .tri-layout-left > * { + pointer-events: auto; + } + } } } @@ -168,7 +144,7 @@ div[class^="col-"] img { } .container { - max-width: $max-width; + max-width: $xxl; margin-left: auto; margin-right: auto; padding-left: $-m; @@ -953,7 +929,7 @@ div[class^="col-"] img { grid-column-gap: $-m; grid-row-gap: 0; &.contained { - max-width: $max-width; + max-width: $xxl; padding-left: $-m; padding-right: $-m; margin-left: auto; diff --git a/resources/assets/sass/_lists.scss b/resources/assets/sass/_lists.scss index 55104680a..8a0db05c2 100644 --- a/resources/assets/sass/_lists.scss +++ b/resources/assets/sass/_lists.scss @@ -304,6 +304,9 @@ ul.pagination { background-size: cover; background-position: 50% 50%; border-radius: 3px; + @include smaller-than($m) { + width: 80px; + } } .entity-list.compact { diff --git a/resources/assets/sass/_variables.scss b/resources/assets/sass/_variables.scss index 229480410..908a65536 100644 --- a/resources/assets/sass/_variables.scss +++ b/resources/assets/sass/_variables.scss @@ -1,10 +1,8 @@ // Variables /////////////// -// Sizes -$max-width: 1400px; - // Screen breakpoints +$xxl: 1400px; $xl: 1100px; $ipad-width: 1028px; // Is actually 1024 but we go over to ensure functionality. $l: 1000px; diff --git a/resources/views/books/index.blade.php b/resources/views/books/index.blade.php index 3cf1a10bf..59be7e362 100644 --- a/resources/views/books/index.blade.php +++ b/resources/views/books/index.blade.php @@ -33,7 +33,7 @@ @section('right') - <div class="actions mb-xl px-xl"> + <div class="actions mb-xl"> <h5>Actions</h5> <div class="icon-list text-primary"> @if($currentUser->can('book-create-all')) diff --git a/resources/views/tri-layout.blade.php b/resources/views/tri-layout.blade.php index a43450ed4..4b169b5c7 100644 --- a/resources/views/tri-layout.blade.php +++ b/resources/views/tri-layout.blade.php @@ -8,24 +8,19 @@ @yield('toolbar') </div> - <div class="flex-fill flex" @yield('container-attrs') > + <div class="tri-layout-container" tri-layout @yield('container-attrs') > - <div sidebar class="sidebar flex print-hidden tri-layout-left" id="sidebar"> - <div class="sidebar-toggle primary-background-light">@icon('caret-right-circle') - </div> - <div class="scroll-body px-xl"> - @yield('left') - </div> + <div class="tri-layout-left print-hidden " id="sidebar"> + @yield('left') </div> - <div class="flex @yield('body-wrap-classes')"> + <div class="@yield('body-wrap-classes') tri-layout-middle"> @yield('body') </div> - <div class="flex tri-layout-right"> + <div class="tri-layout-right print-hidden"> @yield('right') </div> </div> - @stop