[Component] news-navbar

Seperate navbar from news header
RWD done
transition WIP
This commit is contained in:
Tony Yang 2021-02-03 01:35:30 +08:00
parent 2f379e8372
commit 16f2fa5b02
Signed by: t510599
GPG Key ID: D88388851C28715D
5 changed files with 202 additions and 114 deletions

View File

@ -355,82 +355,3 @@ $fontFamily: Noto Sans TC, monospace;
} }
} }
} }
.news-nav {
position: fixed;
text-align: end;
top: 25px;
right: 50px;
display: flex;
flex-direction: column;
border-radius: 15px;
padding: 10px;
box-shadow: 3px 3px 15px $mid-blue;
background: white;
z-index: 5;
&-item {
margin: 0 8px;
padding: 5px 1em;
color: $mid-blue;
font-family: $fontFamily;
cursor: point;
border-right: 3px solid $sky-blue;
&.active {
font-weight: 900;
border-right: 3px solid $mid-blue;
}
}
&-button {
color: $mid-blue;
border: none;
background: transparent;
font-size: 20px;
cursor: point;
&:focus {
outline: none;
}
}
&-contribute-button {
display: inline-block;
border-radius: 6px;
background: $mid-blue;
color: $white;
font-weight: 900;
padding: 0.5em 1em;
font-size: 1.2em;
margin: 1em auto;
}
}
.nav-control-button {
color: $mid-blue;
position: fixed;
z-index: 5;
top: 25px;
right: 50px;
border-radius: 5px;
border: none;
font-size: 24px;
position: flex;
flex-direction: column;
width: 55px;
background-color: white;
box-shadow: -2px 0 15px $mid-blue;
padding: 0 15px;
cursor: pointer;
p {
text-align: end;
}
}
@media screen and (max-width: 1024px) {
.nav-control-button {
top: 250px;
right: 0;
width: 35px;
font-size: 16px;
text-align: left;
padding: 0 10px;
}
}

View File

@ -0,0 +1,114 @@
@import '../color';
@import '../font';
$mobileView: 1024px;
#news-nav {
font-size: 13pt;
line-height: 1em;
z-index: 2;
position: sticky;
top: 25px;
&.fixed {
position: fixed;
top: 25px;
right: 50px;
}
a {
text-decoration: none;
}
.news-nav {
float: right;
text-align: end;
display: flex;
flex-direction: column;
border-radius: 15px;
padding: 10px;
box-shadow: 3px 3px 15px $mid-blue;
background: white;
z-index: 5;
transform: translateX(0);
transition: transform 0.5s ease-in-out;
&-item {
margin: 0 8px;
padding: 5px 1em;
color: $mid-blue;
font-family: $fontFamily;
cursor: point;
border-right: 3px solid $sky-blue;
&.active {
font-weight: 900;
border-right: 3px solid $mid-blue;
}
}
&-button {
color: $mid-blue;
border: none;
background: transparent;
padding: 0.5em 0;
font-size: 20px;
cursor: pointer;
&:focus {
outline: none;
}
}
&-contribute-button {
display: inline-block;
border-radius: 6px;
background: $mid-blue;
color: $white;
font-weight: 900;
padding: 0.5em 1em;
font-size: 1.2em;
margin: 1em auto;
}
}
.nav-control-button {
color: $mid-blue;
position: fixed;
z-index: 5;
top: 25px;
right: 50px;
border-radius: 5px;
border: none;
font-size: 24px;
position: flex;
flex-direction: column;
width: 55px;
background-color: white;
box-shadow: -2px 0 15px $mid-blue;
padding: 0 15px;
cursor: pointer;
p {
text-align: end;
}
}
@media screen and (max-width: $mobileView) {
.nav-control-button {
top: 250px;
right: 0;
width: 35px;
font-size: 16px;
text-align: left;
padding: 0 10px;
}
}
}
@media screen and (max-width: $mobileView) {
#news-nav,
#news-nav.fixed {
position: fixed;
top: 25px;
right: 20px;
}
}

View File

@ -46,30 +46,11 @@
</div> </div>
</div> </div>
</div> </div>
<nav v-if="navVisible">
<div class="news-nav" v-scrollspy="{ selectors: navbarItems }">
<a class="news-nav-item" href="#schedule">重要時程</a>
<a class="news-nav-item" href="#example">投稿主題範例</a>
<a class="news-nav-item" href="#code-of-conduct">Code of Conduct</a>
<a class="news-nav-item" href="#info-section">議程種類</a>
<a class="news-nav-item" href="#process">流程</a>
<a class="news-nav-item" href="#methods">投稿方式</a>
<a class="news-nav-item" href="#review">審稿方式</a>
<a class="news-nav-item" href="#precautions">投稿注意事項</a>
<a class="news-nav-contribute-button" target="_blank" rel="noopener" href="https://forms.gle/XoXJSD2P8dL8X8s2A">我要投稿</a>
<button class="news-nav-button" @click="(e)=>navVisible=!navVisible">&#9650;</button>
</div>
</nav>
<button v-if="!navVisible" class="nav-control-button" @click="(e)=>navVisible=!navVisible">
<p>&#9650;</p>
<p>&#9660;</p>
</button>
</header> </header>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'; import { Component, Prop, Vue } from 'vue-property-decorator';
import ScrollSpyDirective from './ScrollSpyDirective';
const DEAD_LINE = Math.floor( const DEAD_LINE = Math.floor(
new Date('22 Feb 2021 06:24:00 GMT+8').getTime() / 1000 new Date('22 Feb 2021 06:24:00 GMT+8').getTime() / 1000
@ -82,23 +63,10 @@ interface Countdown {
d: number; d: number;
} }
@Component({ @Component({})
directives: {
scrollspy: ScrollSpyDirective
}
})
export default class CfpHeader extends Vue { export default class CfpHeader extends Vue {
private timerId!: number; private timerId!: number;
private navbarItems = [
'#schedule',
'#example',
'#code-of-conduct',
'#info-section',
'#process',
'#methods',
'#review',
'#precautions'
];
private navVisible = false; private navVisible = false;
private countdown: Countdown = { private countdown: Countdown = {
s: 0, s: 0,

View File

@ -0,0 +1,82 @@
<template>
<nav id="news-nav" :class="{ fixed: isNavbarFixed }">
<div v-show="!isMobileView || navVisible" class="news-nav" v-scrollspy="{ selectors: navbarItems }">
<a class="news-nav-item" href="#schedule">重要時程</a>
<a class="news-nav-item" href="#example">投稿主題範例</a>
<a class="news-nav-item" href="#code-of-conduct">Code of Conduct</a>
<a class="news-nav-item" href="#info-section">議程種類</a>
<a class="news-nav-item" href="#process">流程</a>
<a class="news-nav-item" href="#methods">投稿方式</a>
<a class="news-nav-item" href="#review">審稿方式</a>
<a class="news-nav-item" href="#precautions">投稿注意事項</a>
<a class="news-nav-contribute-button" target="_blank" rel="noopener" href="https://forms.gle/XoXJSD2P8dL8X8s2A" v-show="!isMobileView">我要投稿</a>
<button class="news-nav-button" @click="(e)=>navVisible=!navVisible" v-show="isMobileView">&#9650;</button>
</div>
<button v-show="!navVisible && isMobileView" class="nav-control-button" @click="(e)=>navVisible=!navVisible">
<p>&#9650;</p>
<p>&#9660;</p>
</button>
</nav>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import ScrollSpyDirective from './ScrollSpyDirective';
@Component({
directives: {
scrollspy: ScrollSpyDirective
}
})
export default class Navbar extends Vue {
private isMobileView: boolean = false;
private isNavbarFixed = false;
private navVisible: boolean = false;
private navbarItems: string[] = [
'#schedule',
'#example',
'#code-of-conduct',
'#info-section',
'#process',
'#methods',
'#review',
'#precautions'
];
public mounted () {
this.$nextTick().then(() => {
const query: string = '(max-width: 1024px)';
const mq: MediaQueryList = window.matchMedia(query);
if (mq.addEventListener) {
mq.addEventListener('change', this.matchMediaCallback);
} else {
mq.addListener(this.matchMediaCallback);
}
// check first
this.matchMediaCallback(mq);
// observe header: header appears => no fix; header disappears => fix.
const fixObserver: IntersectionObserver = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) {
this.isNavbarFixed = true;
} else {
this.isNavbarFixed = false;
}
});
}, { rootMargin: '25px 0px 0px 0px', threshold: 0 });
fixObserver.observe(document.querySelector('#news-header') as Element);
});
}
private matchMediaCallback (ev: (MediaQueryList | MediaQueryListEvent)) {
this.isMobileView = ev.matches;
// alaways disable navbar while view changing
this.navVisible = false;
}
}
</script>
<style lang="scss" scoped>
@import '@/assets/scss/news/navbar';
</style>

View File

@ -1,5 +1,6 @@
<template> <template>
<div> <div>
<Navbar />
<!-- 重要時程 --> <!-- 重要時程 -->
<section id="schedule"> <section id="schedule">
<h1>重要時程</h1> <h1>重要時程</h1>
@ -57,6 +58,7 @@
import { Component, Prop, Vue } from 'vue-property-decorator'; import { Component, Prop, Vue } from 'vue-property-decorator';
import AgendaCard from './AgendaCard.vue'; import AgendaCard from './AgendaCard.vue';
import Topic from './Topic.vue'; import Topic from './Topic.vue';
import Navbar from './Navbar.vue';
// import data // import data
import themeExample from '../../../template/themeExample.cfp'; import themeExample from '../../../template/themeExample.cfp';
@ -66,7 +68,8 @@ import presentation from '../../../template/presentation.cfp';
@Component({ @Component({
components: { components: {
AgendaCard, AgendaCard,
Topic Topic,
Navbar
} }
}) })
export default class Schedule extends Vue { export default class Schedule extends Vue {