mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-11-23 19:32:29 +01:00
Updated tri-layout on mobile to be tab based
This commit is contained in:
parent
f797d2da20
commit
8d358e4894
@ -3,18 +3,23 @@ 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.scrollCache = {
|
||||
'content': 0,
|
||||
'info': 0,
|
||||
};
|
||||
this.lastTabShown = 'content';
|
||||
|
||||
// Bind any listeners
|
||||
this.mobileTabClick = this.mobileTabClick.bind(this);
|
||||
|
||||
// Watch layout changes
|
||||
this.updateLayout();
|
||||
window.addEventListener('resize', event => {
|
||||
this.updateLayout();
|
||||
});
|
||||
}, {passive: true});
|
||||
}
|
||||
|
||||
updateLayout() {
|
||||
@ -38,16 +43,15 @@ class TriLayout {
|
||||
}
|
||||
|
||||
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);
|
||||
const layoutTabs = document.querySelectorAll('[tri-layout-mobile-tab]');
|
||||
for (let tab of layoutTabs) {
|
||||
tab.addEventListener('click', this.mobileTabClick);
|
||||
}
|
||||
|
||||
this.onDestroy = () => {
|
||||
this.left.removeEventListener('click', mobileSidebarClickBound);
|
||||
this.right.removeEventListener('click', mobileSidebarClickBound);
|
||||
this.middle.removeEventListener('click', mobileContentClickBound);
|
||||
for (let tab of layoutTabs) {
|
||||
tab.removeEventListener('click', this.mobileTabClick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,27 +59,35 @@ class TriLayout {
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Action to run when the mobile info toggle bar is clicked/tapped
|
||||
* @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');
|
||||
mobileTabClick(event) {
|
||||
const tab = event.target.getAttribute('tri-layout-mobile-tab');
|
||||
this.scrollCache[this.lastTabShown] = document.documentElement.scrollTop;
|
||||
|
||||
// Set tab status
|
||||
const activeTabs = document.querySelectorAll('.tri-layout-mobile-tab.active');
|
||||
for (let tab of activeTabs) {
|
||||
tab.classList.remove('active');
|
||||
}
|
||||
event.target.classList.add('active');
|
||||
|
||||
// Toggle section
|
||||
const showInfo = (tab === 'info');
|
||||
this.elem.classList.toggle('show-info', showInfo);
|
||||
|
||||
// Set the scroll position from cache
|
||||
const pageHeader = document.querySelector('header');
|
||||
const defaultScrollTop = pageHeader.getBoundingClientRect().bottom;
|
||||
document.documentElement.scrollTop = this.scrollCache[tab] || defaultScrollTop;
|
||||
setTimeout(() => {
|
||||
document.documentElement.scrollTop = this.scrollCache[tab] || defaultScrollTop;
|
||||
}, 50);
|
||||
|
||||
this.lastTabShown = tab;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,13 +9,14 @@ header .grid {
|
||||
@include smaller-than($l) {
|
||||
header .grid {
|
||||
grid-template-columns: 1fr;
|
||||
grid-row-gap: 0;
|
||||
}
|
||||
}
|
||||
|
||||
header {
|
||||
position: relative;
|
||||
display: block;
|
||||
z-index: 2;
|
||||
z-index: 6;
|
||||
top: 0;
|
||||
background-color: $primary-dark;
|
||||
color: #fff;
|
||||
@ -202,6 +203,25 @@ header .search-box {
|
||||
}
|
||||
}
|
||||
|
||||
.tri-layout-mobile-tabs {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 5;
|
||||
background-color: #FFF;
|
||||
border-bottom: 1px solid #DDD;
|
||||
box-shadow: $bs-card;
|
||||
}
|
||||
.tri-layout-mobile-tab {
|
||||
text-align: center;
|
||||
border-bottom: 3px solid #BBB;
|
||||
&:first-child {
|
||||
border-right: 1px solid #DDD;
|
||||
}
|
||||
&.active {
|
||||
border-bottom-color: currentColor;
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumbs {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@ -226,6 +246,18 @@ header .search-box {
|
||||
}
|
||||
}
|
||||
|
||||
@include smaller-than($l) {
|
||||
.breadcrumbs .icon-list-item {
|
||||
padding: $-xs;
|
||||
> span + span {
|
||||
display: none;
|
||||
}
|
||||
> span:first-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb-listing {
|
||||
position: relative;
|
||||
.breadcrumb-listing-toggle {
|
||||
|
@ -49,13 +49,17 @@
|
||||
&.v-center {
|
||||
align-items: center;
|
||||
}
|
||||
&.no-gap {
|
||||
grid-row-gap: 0;
|
||||
grid-column-gap: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@include smaller-than($m) {
|
||||
.grid.third {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
.grid.half, .grid.left-focus, .grid.right-focus {
|
||||
.grid.half:not(.no-break), .grid.left-focus:not(.no-break), .grid.right-focus:not(.no-break) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.grid.half.collapse-xs {
|
||||
@ -241,8 +245,10 @@ body.flexbox {
|
||||
@include smaller-than($l) {
|
||||
.tri-layout-container {
|
||||
grid-template-areas: none;
|
||||
grid-template-columns: 10% 90%;
|
||||
grid-template-columns: 1fr;
|
||||
grid-column-gap: 0;
|
||||
padding-right: $-xs;
|
||||
padding-left: $-xs;
|
||||
.tri-layout-left-contents, .tri-layout-right-contents {
|
||||
padding-left: $-m;
|
||||
padding-right: $-m;
|
||||
@ -252,33 +258,50 @@ body.flexbox {
|
||||
z-index: 0;
|
||||
}
|
||||
.tri-layout-left > *, .tri-layout-right > * {
|
||||
display: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
.tri-layout-right, .tri-layout-left, .tri-layout-middle {
|
||||
.tri-layout-left, .tri-layout-right {
|
||||
grid-area: none;
|
||||
grid-column: 1/3;
|
||||
grid-column: 1/1;
|
||||
grid-row: 1;
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
.tri-layout-middle {
|
||||
grid-row: 1/3;
|
||||
grid-column: 2/3;
|
||||
grid-area: none;
|
||||
grid-row: 3;
|
||||
grid-column: 1/1;
|
||||
z-index: 1;
|
||||
overflow: hidden;
|
||||
transition: transform ease-in-out 240ms;
|
||||
}
|
||||
.tri-layout-left {
|
||||
grid-row: 2;
|
||||
}
|
||||
&.mobile-open {
|
||||
&.show-info {
|
||||
overflow: hidden;
|
||||
.tri-layout-middle {
|
||||
transform: translateX(90%);
|
||||
display: none;
|
||||
}
|
||||
.tri-layout-right > *, .tri-layout-left > * {
|
||||
display: block;
|
||||
pointer-events: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@include larger-than($l) {
|
||||
.tri-layout-mobile-tabs {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@include smaller-than($m) {
|
||||
.tri-layout-container {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.tri-layout-left-contents > div, .tri-layout-right-contents > div {
|
||||
opacity: 0.6;
|
||||
|
@ -60,6 +60,10 @@ return [
|
||||
'view_profile' => 'View Profile',
|
||||
'edit_profile' => 'Edit Profile',
|
||||
|
||||
// Layout tabs
|
||||
'tab_info' => 'Info',
|
||||
'tab_content' => 'Content',
|
||||
|
||||
// Email Content
|
||||
'email_action_help' => 'If you’re having trouble clicking the ":actionText" button, copy and paste the URL below into your web browser:',
|
||||
'email_rights' => 'All rights reserved',
|
||||
|
@ -4,6 +4,17 @@
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="tri-layout-mobile-tabs text-primary" >
|
||||
<div class="grid half no-break no-gap">
|
||||
<div class="tri-layout-mobile-tab px-m py-s" tri-layout-mobile-tab="info">
|
||||
{{ trans('common.tab_info') }}
|
||||
</div>
|
||||
<div class="tri-layout-mobile-tab px-m py-s active" tri-layout-mobile-tab="content">
|
||||
{{ trans('common.tab_content') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tri-layout-container" tri-layout @yield('container-attrs') >
|
||||
|
||||
<div class="tri-layout-left print-hidden pt-m" id="sidebar">
|
||||
|
Loading…
Reference in New Issue
Block a user