[Add] navbar scrollspy directive
Add navbar scrollspy navbar style improvement
This commit is contained in:
parent
5141a28a50
commit
dd3708d493
@ -4,3 +4,4 @@ $pale-grey: #f0f7fd;
|
||||
$dark-slate-blue: #1f4163;
|
||||
$dark-sky-blue: #3d93e9;
|
||||
$slate-blue: #5f7a95;
|
||||
$sky-blue: #9dc5ec;
|
@ -369,10 +369,17 @@ $fontFamily: Noto Sans TC, monospace;
|
||||
background: white;
|
||||
z-index: 5;
|
||||
&-item {
|
||||
margin: 5px 8px;
|
||||
margin: 0 8px;
|
||||
padding: 5px 1em;
|
||||
color: $mid-blue;
|
||||
font-family: $fontFamily;
|
||||
cursor: point;
|
||||
border-right: 2px solid $sky-blue;
|
||||
|
||||
&.active {
|
||||
font-weight: 900;
|
||||
border-right: 2px solid $mid-blue;
|
||||
}
|
||||
}
|
||||
&-button {
|
||||
color: $mid-blue;
|
||||
|
@ -47,7 +47,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<nav v-if="navVisible">
|
||||
<div class="news-nav">
|
||||
<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>
|
||||
@ -69,6 +69,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||
import ScrollSpyDirective from './ScrollSpyDirective';
|
||||
|
||||
const DEAD_LINE = Math.floor(
|
||||
new Date('22 Feb 2021 06:24:00 GMT+8').getTime() / 1000
|
||||
@ -81,9 +82,23 @@ interface Countdown {
|
||||
d: number;
|
||||
}
|
||||
|
||||
@Component
|
||||
@Component({
|
||||
directives: {
|
||||
scrollspy: ScrollSpyDirective
|
||||
}
|
||||
})
|
||||
export default class CfpHeader extends Vue {
|
||||
private timerId!: number;
|
||||
private navbarItems = [
|
||||
'#schedule',
|
||||
'#example',
|
||||
'#code-of-conduct',
|
||||
'#info-section',
|
||||
'#process',
|
||||
'#methods',
|
||||
'#review',
|
||||
'#precautions'
|
||||
];
|
||||
private navVisible = false;
|
||||
private countdown: Countdown = {
|
||||
s: 0,
|
||||
|
37
src/components/news/ScrollSpyDirective.ts
Normal file
37
src/components/news/ScrollSpyDirective.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import Vue, { DirectiveOptions, VNode, VNodeDirective } from 'vue';
|
||||
|
||||
let selectors!: string[];
|
||||
let observer!: IntersectionObserver;
|
||||
|
||||
const ScrollSpyDirective: DirectiveOptions = {
|
||||
bind (el: Element, binding: VNodeDirective , vnode: VNode) {
|
||||
selectors = binding.value.selectors;
|
||||
|
||||
// highlight first element
|
||||
el.querySelector(`[href="${location.hash || selectors[0] || ''}"]`)?.classList.toggle('active', true);
|
||||
|
||||
const config = {
|
||||
rootMargin: '-10% 0px -80% 0px',
|
||||
threshold: 0
|
||||
};
|
||||
|
||||
observer = new IntersectionObserver((entries, observer) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
selectors.forEach((selector: string) => {
|
||||
el.querySelector(`[href="${selector}"`)?.classList.toggle('active', selector === `#${entry.target.id}`);
|
||||
});
|
||||
}
|
||||
});
|
||||
}, config);
|
||||
|
||||
selectors.forEach((selector: string) => {
|
||||
observer.observe(document.querySelector(selector) as Element);
|
||||
});
|
||||
},
|
||||
unbind () {
|
||||
observer.disconnect();
|
||||
}
|
||||
};
|
||||
|
||||
export default ScrollSpyDirective;
|
Loading…
x
Reference in New Issue
Block a user