Add mobile navigation

This commit is contained in:
Ramon Wenger 2019-04-08 17:16:35 +02:00
parent db96fbac84
commit d879aa1955
11 changed files with 306 additions and 18 deletions

View File

@ -1,7 +1,8 @@
<template>
<div :class="{'no-scroll': showModal}" class="app">
<div :class="{'no-scroll': showModal || showMobileNavigation}" class="app">
<component :is="showModal" v-if="showModal"></component>
<component :is="layout"></component>
<mobile-navigation v-if="showMobileNavigation"></mobile-navigation>
</div>
</template>
@ -10,6 +11,7 @@
import SimpleLayout from '@/layouts/SimpleLayout';
import BlankLayout from '@/layouts/BlankLayout';
import Modal from '@/components/Modal';
import MobileNavigation from '@/components/MobileNavigation';
import NewContentBlockWizard from '@/components/content-block-form/NewContentBlockWizard';
import EditContentBlockWizard from '@/components/content-block-form/EditContentBlockWizard';
import NewRoomEntryWizard from '@/components/rooms/room-entries/NewRoomEntryWizard';
@ -21,6 +23,8 @@
import FullscreenInfographic from '@/components/FullscreenInfographic';
import FullscreenVideo from '@/components/FullscreenVideo';
import {mapGetters} from 'vuex';
export default {
name: 'App',
@ -29,6 +33,7 @@
SimpleLayout,
BlankLayout,
Modal,
MobileNavigation,
NewContentBlockWizard,
EditContentBlockWizard,
NewRoomEntryWizard,
@ -45,9 +50,7 @@
layout() {
return (this.$route.meta.layout || 'default') + '-layout';
},
showModal() {
return this.$store.state.showModal
}
...mapGetters(['showModal', 'showMobileNavigation'])
},
mounted() {
@ -58,7 +61,14 @@
<style lang="scss">
@import "styles/main.scss";
body {
overflow: hidden;
height: 100vh;
}
.app {
overflow-y: auto;
height: 100vh;
/*for IE10+*/
display: flex;
}

View File

@ -1,7 +1,7 @@
<template>
<header class="header-bar">
<top-navigation></top-navigation>
<router-link to="/" class="header-bar__logo">skillbox</router-link>
<router-link to="/" class="header-bar__logo"><logo></logo></router-link>
<div class="user-header">
<user-widget v-bind="me"></user-widget>
<logout-widget></logout-widget>
@ -16,6 +16,7 @@
import BookNavigation from '@/components/book-navigation/BookNavigation';
import UserWidget from '@/components/UserWidget.vue';
import LogoutWidget from '@/components/LogoutWidget.vue';
import Logo from '@/components/icons/Logo';
import ME_QUERY from '@/graphql/gql/meQuery.gql';
@ -24,7 +25,8 @@
TopNavigation,
UserWidget,
LogoutWidget,
BookNavigation
BookNavigation,
Logo
},
computed: {

View File

@ -0,0 +1,55 @@
<template>
<div class="mobile-header">
<router-link to="/">
<logo></logo>
</router-link>
<a @click="showMobileNavigation">
<hamburger class="mobile-header__hamburger"></hamburger>
</a>
</div>
</template>
<script>
import Logo from '@/components/icons/Logo';
import Hamburger from '@/components/icons/Hamburger';
export default {
components: {
Logo,
Hamburger
},
methods: {
showMobileNavigation() {
this.$store.dispatch('showMobileNavigation', true);
}
}
}
</script>
<style scoped lang="scss">
@import "@/styles/_variables.scss";
@import "@/styles/_mixins.scss";
.mobile-header {
justify-content: space-between;
align-items: center;
display: flex;
@include desktop {
display: none;
}
padding: 0 $medium-spacing;
&__hamburger {
width: 30px;
height: 30px;
fill: $color-grey;
}
}
</style>

View File

@ -0,0 +1,118 @@
<template>
<div class="mobile-navigation">
<top-navigation class="mobile-navigation__main" :mobile="true"></top-navigation>
<div class="mobile-navigation__close-button" @click="hideMobileNavigation">
<cross class="mobile-navigation__close-icon"></cross>
</div>
<div class="mobile-navigation__subnavigation"></div>
<div class="mobile-navigation__secondary">
<user-widget class="mobile-navigation__user-widget" v-bind="me"></user-widget>
<logout-widget class="mobile-navigation__logout-widget"></logout-widget>
</div>
</div>
</template>
<script>
import Cross from '@/components/icons/Cross';
import UserWidget from '@/components/UserWidget';
import LogoutWidget from '@/components/LogoutWidget';
import TopNavigation from '@/components/TopNavigation';
import {meQuery} from '@/graphql/queries';
export default {
components: {
TopNavigation,
Cross,
UserWidget,
LogoutWidget
},
methods: {
hideMobileNavigation() {
this.$store.dispatch('showMobileNavigation', false);
}
},
apollo: {
me: meQuery
},
data() {
return {
me: {}
}
}
}
</script>
<style scoped lang="scss">
@import "@/styles/_variables.scss";
@import "@/styles/_mixins.scss";
.mobile-navigation {
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
background-color: white;
z-index: 20;
display: grid;
grid-template-columns: 1fr 50px;
grid-template-rows: 50px 100px auto 100px;
grid-template-areas: "m m" "m m" "s s";
&--with-subnavigation {
grid-template-areas: "m m" "m m" "sub sub" "s s";
}
height: 100vh;
overflow-y: auto;
@include desktop {
display: none;
}
&__main {
background-color: $color-brand;
padding: $medium-spacing;
grid-area: m;
}
&__main-link {
}
&__close-button {
grid-row: 1;
grid-column: 2;
align-self: center;
justify-self: center;
}
&__close-icon {
width: 30px;
height: 30px;
opacity: 0.5;
fill: $color-white;
}
&__secondary {
grid-area: s;
padding: $medium-spacing;
display: flex;
flex-direction: column;
}
&__user-widget {
margin-bottom: $small-spacing;
}
&__logout-widget {
margin-left: -20px;
}
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<nav class="top-navigation">
<nav class="top-navigation" :class="{'top-navigation--mobile': mobile}">
<router-link to="/book/topic/geld-und-kauf" active-class="top-navigation__link--active"
:class="{'top-navigation__link--active': isActive('book')}"
class="top-navigation__link">Inhalte
@ -13,6 +13,12 @@
<script>
export default {
props: {
mobile: {
default: false
}
},
methods: {
isActive(linkName) {
return linkName === 'book' && this.$route.path.indexOf('module') > -1;
@ -23,6 +29,7 @@
<style scoped lang="scss">
@import "@/styles/_variables.scss";
@import "@/styles/_mixins.scss";
.top-navigation {
display: flex;
@ -38,5 +45,22 @@
color: $color-brand;
}
}
$parent: &;
&--mobile {
flex-direction: column;
#{$parent}__link {
color: rgba($color-white, 0.6);
@include heading-4;
line-height: 2em;
padding: 0;
&--active {
color: $color-white;
}
}
}
}
</style>

View File

@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<path d="M15,50a2.48,2.48,0,0,0,2.49,2.5h65a2.5,2.5,0,0,0,0-5h-65A2.5,2.5,0,0,0,15,50Z"/>
<path d="M15,20.5A2.48,2.48,0,0,0,17.49,23h65a2.5,2.5,0,0,0,0-5h-65A2.5,2.5,0,0,0,15,20.5Z"/>
<path d="M15,79.5A2.48,2.48,0,0,0,17.49,82h65a2.5,2.5,0,0,0,0-5h-65A2.5,2.5,0,0,0,15,79.5Z"/>
</svg>
</template>

View File

@ -0,0 +1,37 @@
<template>
<svg class="logo" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 1350 250">
<path
d="M304.4,242.15a60,60,0,0,1-19.59-3.1,64.2,64.2,0,0,1-17.6-9.63l-2.94-2.22,21.17-34,3.58,3.21a21.91,21.91,0,0,0,6,4,15.21,15.21,0,0,0,5.81,1.09c4,0,6.51-1.44,8.08-4.68l1.15-2.19L263.73,85.72H313.8L334.27,143l17.38-57.3h48.8L353,208.39c-4.53,11.34-10.91,19.87-19,25.41h0C326,239.34,316,242.15,304.4,242.15Zm-29.33-17a53.63,53.63,0,0,0,12.38,6.3,51.94,51.94,0,0,0,17,2.66c10,0,18.42-2.33,25.12-6.94h0c6.71-4.62,12.1-11.92,16-21.71L388.67,93.79h-31l-22.74,75-26.79-75H275.94L319,195l-2.88,5.47c-2.87,5.92-8.18,9.11-15.29,9.11a23.28,23.28,0,0,1-8.88-1.69,24.83,24.83,0,0,1-4.58-2.53Z"
style="fill:#36c0a1"/>
<path
d="M458.66,113a12.63,12.63,0,0,0-6.43,1.39,4.55,4.55,0,0,0-2.36,4.18q0,3.22,4.4,5.25a93.59,93.59,0,0,0,14,4.61,178.08,178.08,0,0,1,21.33,7.29,40.28,40.28,0,0,1,14.79,11q6.32,7.39,6.33,19,0,17.8-14,28.19t-37.19,10.4A102.76,102.76,0,0,1,430,200.15a84.64,84.64,0,0,1-25.4-12.33l13.29-27.22a97.33,97.33,0,0,0,21.76,10.72A64.21,64.21,0,0,0,460.16,175a14.94,14.94,0,0,0,7.07-1.39,4.33,4.33,0,0,0,2.57-4q0-3.22-4.18-5.25a84.51,84.51,0,0,0-13.83-4.61A157.5,157.5,0,0,1,431,152.67a40,40,0,0,1-14.58-10.93q-6.22-7.29-6.22-18.86,0-18,13.72-28.51t36-10.5q26.79,0,51.23,14.15l-14.36,27.22Q473,113,458.66,113Z"
style="fill:#36c0a1"/>
<path d="M604.69,202.4l-21.22-40.51-8.79,9.22v31.3h-43.3V43.35h43.3v77.38l32.15-34.94h48.87l-42.66,45,42.87,71.6Z"
style="fill:#36c0a1"/>
<path
d="M712.25,36.49q6.22,6.22,6.22,16.08t-6.22,16.08q-6.22,6.22-16.08,6.22T680,68.64q-6.33-6.21-6.32-16.08T680,36.49q6.32-6.21,16.18-6.22T712.25,36.49Zm-37.51,49.3H718V202.4h-43.3Z"
style="fill:#36c0a1"/>
<path d="M748.47,43.35h43.3V202.4h-43.3Z" style="fill:#36c0a1"/>
<path d="M823.5,43.35h43.3V202.4H823.5Z" style="fill:#36c0a1"/>
<path
d="M1002.06,91.79A50.33,50.33,0,0,1,1021,113q6.75,13.72,6.75,31.73,0,17.8-6.54,31.19a48.35,48.35,0,0,1-18.54,20.69q-12,7.29-27.87,7.29A44,44,0,0,1,956.19,200a40.21,40.21,0,0,1-14.36-11.15v13.5h-43.3V43.35h43.3V99.29a38.85,38.85,0,0,1,13.93-11.15,41.53,41.53,0,0,1,18-3.86Q989.85,84.29,1002.06,91.79Zm-23.8,70.63q5.79-7.18,5.79-18.76t-5.79-18.76a18.82,18.82,0,0,0-15.43-7.18,18.59,18.59,0,0,0-15.22,7.18q-5.79,7.19-5.79,18.76t5.79,18.76a18.58,18.58,0,0,0,15.22,7.18A18.8,18.8,0,0,0,978.27,162.42Z"
style="fill:#36c0a1"/>
<path
d="M1142.8,91.69a54.24,54.24,0,0,1,22.62,20.9q8,13.5,8,31.51,0,17.8-8,31.4a54,54,0,0,1-22.62,21q-14.58,7.4-34.08,7.4t-34.19-7.4a53.86,53.86,0,0,1-22.73-21q-8-13.61-8-31.4,0-18,8-31.51a54.08,54.08,0,0,1,22.73-20.9q14.68-7.4,34.19-7.4T1142.8,91.69Zm-49.52,34.08q-5.79,7.18-5.79,18.76,0,11.79,5.79,18.86a18.92,18.92,0,0,0,15.43,7.07,18.7,18.7,0,0,0,15.22-7.07q5.79-7.07,5.79-18.86,0-11.58-5.79-18.76a18.6,18.6,0,0,0-15.22-7.18A18.81,18.81,0,0,0,1093.28,125.77Z"
style="fill:#36c0a1"/>
<path
d="M1176.45,85.79h49.73L1242.26,116l18-30.23h47.16L1271,142.6l39,59.81h-49.73l-18-33-20.58,33h-47.59l39-59.59Z"
style="fill:#36c0a1"/>
<path
d="M245,105.8A38.35,38.35,0,0,0,229.9,89.74h0a46.56,46.56,0,0,0-46.21,1.09A41.77,41.77,0,0,0,171.45,103a38.76,38.76,0,0,0-11.67-12,42.9,42.9,0,0,0-24.06-6.82,44.09,44.09,0,0,0-21.4,5.16,41.05,41.05,0,0,0-8.13,5.83v-9.4H58V201.83h48.19V144.37c0-5.32,1.23-9.42,3.77-12.55a11.7,11.7,0,0,1,9.27-4.46,9.48,9.48,0,0,1,7.75,3.35c2.09,2.45,3.11,5.75,3.11,10.09v61h48.19V144.37c0-5.26,1.24-9.49,3.69-12.59a11.44,11.44,0,0,1,9.15-4.43,9.48,9.48,0,0,1,7.75,3.35c2.09,2.45,3.11,5.75,3.11,10.09v61h48.19V129.28A51.17,51.17,0,0,0,245,105.8Zm-2.87,88h-32v-53c0-6.25-1.7-11.41-5-15.33a17.51,17.51,0,0,0-14-6.18h0a19.38,19.38,0,0,0-15.37,7.49c-3.61,4.55-5.44,10.48-5.44,17.6v49.39h-32v-53c0-6.25-1.7-11.41-5-15.33a17.53,17.53,0,0,0-14-6.18h0a19.66,19.66,0,0,0-15.44,7.45c-3.69,4.56-5.57,10.49-5.57,17.63v49.39h-32v-100h32v18.16h5.19l2.25-3.54a34.63,34.63,0,0,1,12.63-12,36.13,36.13,0,0,1,17.53-4.17,35,35,0,0,1,19.62,5.49,31.51,31.51,0,0,1,12.17,15.38l.46,1.18h6.52l.45-1a36.75,36.75,0,0,1,50.91-16.55,30,30,0,0,1,11.93,12.74,43.2,43.2,0,0,1,4.33,19.81Z"
style="fill:#36c0a1"/>
</svg>
</template>
<style scoped lang="scss">
.logo {
width: 250px;
height: 48px;
}
</style>

View File

@ -3,6 +3,8 @@
<header-bar class="header skillbox__header">
</header-bar>
<mobile-header class="header skillbox__header skillbox__header--mobile"></mobile-header>
<filter-bar v-if="showFilter" class="skillbox__filter-bar"></filter-bar>
<router-view class="skillbox__content"></router-view>
@ -11,13 +13,15 @@
</template>
<script>
import FilterBar from '@/components/FilterBar.vue';
import HeaderBar from '@/components/HeaderBar.vue';
import FilterBar from '@/components/FilterBar';
import HeaderBar from '@/components/HeaderBar';
import MobileHeader from '@/components/MobileHeader';
export default {
components: {
FilterBar,
HeaderBar
HeaderBar,
MobileHeader
},
computed: {

View File

@ -1,6 +1,9 @@
<template>
<div class="start-page">
<header-bar class="start-page__header"></header-bar>
<mobile-header class="start-page__header start-page__header--mobile"></mobile-header>
<div class="start-page__sections start-sections">
<section-block
@ -53,9 +56,11 @@
import RoomsIllustration from '@/components/illustrations/RoomsIllustration';
import {meQuery} from '@/graphql/queries';
import MobileHeader from "@/components/MobileHeader";
export default {
components: {
MobileHeader,
HeaderBar,
SectionBlock,
NewsTeaser,

View File

@ -20,6 +20,8 @@ import portfolio from '@/pages/portfolio'
import project from '@/pages/project'
import newProject from '@/pages/newProject'
import store from '@/store/index';
const routes = [
{path: '/', component: start, meta: {layout: 'blank'}},
{
@ -47,7 +49,12 @@ const routes = [
{path: '/edit-room/:id', name: 'edit-room', component: editRoom, props: true},
{path: '/room/:slug', name: 'room', component: room, props: true},
{path: '/article/:slug', name: 'article', component: article, meta: {layout: 'simple'}},
{path: '/basic-knowledge/', name: 'basic-knowledge-overview', component: basicknowledgeOverview, meta: {subnavigation: true}},
{
path: '/basic-knowledge/',
name: 'basic-knowledge-overview',
component: basicknowledgeOverview,
meta: {subnavigation: true}
},
{path: '/basic-knowledge/:slug', name: 'basic-knowledge', component: basicknowledge, meta: {layout: 'simple'}},
{path: '/submission/:id', name: 'submission', component: submission, meta: {layout: 'simple'}},
{path: '/portfolio', name: 'portfolio', component: portfolio},
@ -68,7 +75,8 @@ const routes = [
];
Vue.use(Router);
export default new Router({
const router = new Router({
routes,
mode: 'history',
scrollBehavior(to, from, savedPosition) {
@ -77,4 +85,8 @@ export default new Router({
}
return {x: 0, y: 0}
}
})
});
router.afterEach((to, from) => {
store.dispatch('showMobileNavigation', false);
});
export default router;

View File

@ -9,6 +9,7 @@ export default new Vuex.Store({
state: {
specialContainerClass: '',
showModal: '',
showMobileNavigation: false,
contentBlockPosition: {},
scrollPosition: 0,
filterForSchoolClass: '',
@ -27,7 +28,14 @@ export default new Vuex.Store({
vimeoId: null
},
getters: {},
getters: {
showModal: state => {
return state.showModal
},
showMobileNavigation: state => {
return state.showMobileNavigation
}
},
actions: {
setSpecialContainerClass({commit}, payload) {
@ -108,6 +116,9 @@ export default new Vuex.Store({
commit('setVimeoId', payload);
dispatch('showModal', 'fullscreen-video');
},
showMobileNavigation({commit}, payload) {
commit('setShowMobileNavigation', payload);
}
},
mutations: {
@ -158,6 +169,9 @@ export default new Vuex.Store({
},
setVimeoId(state, payload) {
state.vimeoId = payload;
},
setShowMobileNavigation(state, payload) {
state.showMobileNavigation = payload;
}
}
})