Skip to content

Commit

Permalink
Allow to toggle sidebar and always show the toggle
Browse files Browse the repository at this point in the history
Signed-off-by: Marco Ambrosini <[email protected]>
  • Loading branch information
marcoambrosini authored and skjnldsv committed Apr 8, 2020
1 parent 2605529 commit 6c6bd17
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 83 deletions.
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
],
"dependencies": {
"@nextcloud/axios": "^1.1.0",
"@nextcloud/event-bus": "^1.1.4",
"@nextcloud/l10n": "^1.1.0",
"@nextcloud/router": "^1.0.0",
"core-js": "^3.4.4",
Expand Down
64 changes: 29 additions & 35 deletions src/components/AppContent/AppContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
- @copyright Copyright (c) 2019 Christoph Wurst <[email protected]>
-
- @author Christoph Wurst <[email protected]>
- @author Marco Ambrosini <[email protected]>
- @author John Molakvoæ <[email protected]>
-
- @license GNU AGPL version 3 or any later version
-
Expand All @@ -21,78 +23,70 @@
-->

<template>
<main id="app-content" class="no-snapper" :style="opened ? 'transform: translateX(300px)' : ''">
<AppNavigationToggle :aria-expanded="opened"
aria-controls="app-navigation"
@click="toggleNavigation" />
<main id="app-content" class="no-snapper">
<!-- @slot Provide content to the app content -->
<slot />
</main>
</template>

<script>
import Hammer from 'hammerjs'
import AppNavigationToggle from '../AppNavigationToggle'
import { emit } from '@nextcloud/event-bus'
/**
* App content container to be used for the main content of your app
*
*/
export default {
name: 'AppContent',
components: {
AppNavigationToggle,
},
data() {
return {
// closed by default on mobile mode
opened: false,
}
props: {
// Allows to disable the control by swipe of the app navigation open state
allowSwipeNavigation: {
type: Boolean,
default: true,
},
},
mounted() {
this.mc = new Hammer(this.$el, { cssProps: { userSelect: 'text' } })
this.mc.on('swipeleft swiperight', e => {
this.handleSwipe(e)
})
if (this.allowSwipeNavigation) {
this.mc = new Hammer(this.$el, { cssProps: { userSelect: 'text' } })
this.mc.on('swipeleft swiperight', this.handleSwipe)
}
},
unmounted() {
this.mc.off('swipeleft swiperight')
this.mc.destroy()
beforeDestroy() {
this.mc.off('swipeleft swiperight', this.handleSwipe)
},
methods: {
/**
* Toggle the navigation
*
* @param {Boolean} [state] set the state instead of inverting the current one
*/
toggleNavigation(state) {
this.opened = state || !this.opened
this.opened
? document.body.classList.add('nav-open')
: document.body.classList.remove('nav-open')
},
// handle the swipe event
handleSwipe(e) {
const minSwipeX = 70
const touchzone = 40
const startX = e.srcEvent.pageX - e.deltaX
const hasEnoughDistance = Math.abs(e.deltaX) > minSwipeX
if (hasEnoughDistance && startX < touchzone) {
this.toggleNavigation(true)
} else if (this.opened && hasEnoughDistance && startX < touchzone + 300) {
this.toggleNavigation(false)
emit('toggle-navigation', {
open: true,
})
} else if (hasEnoughDistance && startX < touchzone + 300) {
emit('toggle-navigation', {
open: false,
})
}
},
},
}
</script>
<style lang="scss" scoped>
#app-content {
z-index: 1000;
background-color: var(--color-main-background);
position: relative;
flex-basis: 100vw;
min-height: 100%;
transition: transform var(--animation-quick);
// Overriding server styles TODO: cleanup!
margin: 0 !important;
}
</style>
142 changes: 116 additions & 26 deletions src/components/AppNavigation/AppNavigation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
- @copyright Copyright (c) 2019 Christoph Wurst <[email protected]>
-
- @author Christoph Wurst <[email protected]>
- @author John Molakvoæ <[email protected]>
- @author Marco Ambrosini <[email protected]>
-
- @license GNU AGPL version 3 or any later version
Expand All @@ -20,34 +21,118 @@
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-->
<docs>
The navigation bar can be open and closed from anywhere in the app using the
nextcloud event bus.

### Install the event bus package

```bash
npm i -S @nextcloud/event-bus
```

### Usage

#### Open the navigation

```js static
import { emit } from '@nextcloud/event-bus'
emit('toggle-navigation', {
open: true,
})
```

#### Close the navigation

```js static
import { emit } from '@nextcloud/event-bus'
emit('toggle-navigation', {
open: false,
})
```

</docs>

<template>
<div id="app-navigation" class="vue">
<div
class="app-navigation"
:class="{'app-navigation--close':!open }">
<AppNavigationToggle :open.sync="open" />
<slot />
</div>
</template>

<script>
import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus'
import AppNavigationToggle from '../AppNavigationToggle/AppNavigationToggle'
import isMobile from '../../mixins/isMobile'
export default {
name: 'AppNavigation',
components: {
AppNavigationToggle,
},
mixins: [isMobile],
data() {
return {
open: true,
}
},
watch: {
isMobile() {
this.open = !this.isMobile
},
},
mounted() {
subscribe('toggle-navigation', this.toggleNavigationByEventBus)
// Emit an event with the initial state of the navigation
emit('navigation-toggled', {
open: this.open,
})
},
unmounted() {
this.mc.off('swipeleft swiperight')
this.mc.destroy()
unsubscribe('toggle-navigation', this.toggleNavigationByEventBus)
},
methods: {
/**
* Toggle the navigation
*
* @param {Boolean} [state] set the state instead of inverting the current one
*/
toggleNavigation(state) {
this.open = state || !this.open
emit('navigation-toggled', {
open: this.open,
})
},
toggleNavigationByEventBus({ open }) {
this.toggleNavigation(open)
},
},
}
</script>

<style lang="scss" scoped>
@import '../assets/variables.scss';
#app-navigation {
.app-navigation {
will-change: transform;
transition: transform var(--animation-quick);
transition: transform var(--animation-quick), margin var(--animation-quick);
width: $navigation-width;
position: fixed;
position: sticky;
position: -webkit-sticky;
top: $header-height;
left: 0;
z-index: 500;
overflow-y: auto;
overflow-x: hidden;
// Do not use vh because of mobile headers
// are included in the calculation
height: calc(100% - #{$header-height});
// Above appcontent
z-index: 2000;
height: calc(100vh - #{$header-height});
box-sizing: border-box;
background-color: var(--color-main-background);
-webkit-user-select: none;
Expand All @@ -59,25 +144,30 @@ export default {
flex-direction: column;
flex-grow: 0;
flex-shrink: 0;
}
//list of navigation items
ul {
position: relative;
height: 100%;
width: inherit;
overflow-x: hidden;
overflow-y: auto;
box-sizing: border-box;
display: flex;
flex-direction: column;
&--close {
margin-left: - $navigation-width;
transform: translateX(-100%);
}
//list of navigation items
ul {
position: relative;
height: 100%;
width: inherit;
overflow-x: hidden;
overflow-y: auto;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
}
// mobile view only
// When on mobile, we make the navigation slide over the appcontent
@media only screen and (max-width: $breakpoint-mobile) {
// if navigation is shown
.nav-open #app-navigation {
transform: translateX(0);
.app-navigation:not(.app-navigation--close) {
margin-left: - $navigation-width;
}
}
</style>
Loading

0 comments on commit 6c6bd17

Please sign in to comment.