pinafore/src/routes/_components/NavItem.html

184 lines
4.7 KiB
HTML
Raw Normal View History

<a class='main-nav-link {selected ? "selected" : ""}'
aria-label={ariaLabel}
aria-current={selected}
on:click="onClick(event)"
rel="prefetch"
{href} >
<div class="nav-icon-and-label">
<NavItemIcon
{showBadge}
{badgeNumber}
{svg}
/>
<span class="nav-link-label">{label}</span>
</div>
<div class="nav-indicator"
nav-indicator-key={name}
ref:indicator
></div>
2018-01-13 07:24:05 +00:00
</a>
<style>
.main-nav-link {
2018-01-13 07:24:05 +00:00
text-decoration: none;
display: flex;
justify-content: center;
align-items: center;
flex: 1;
flex-direction: column;
}
.nav-icon-and-label {
2018-03-27 16:34:29 +00:00
padding: 15px 20px;
2018-01-13 07:24:05 +00:00
display: flex;
justify-content: center;
align-items: center;
2018-03-27 16:34:29 +00:00
flex: 1;
2018-01-13 07:24:05 +00:00
}
.main-nav-link.selected {
2018-01-13 07:24:05 +00:00
background: var(--nav-a-selected-bg);
}
.main-nav-link.selected:hover {
2018-01-13 07:24:05 +00:00
background: var(--nav-a-selected-bg-hover);
}
.nav-indicator {
width: 100%;
height: 1px;
background: var(--nav-a-border);
transform-origin: left;
}
.nav-indicator.animate {
transition: transform 333ms ease-in-out;
will-change: transform;
}
.main-nav-link:hover .nav-indicator {
background: var(--nav-a-border-hover);
}
.main-nav-link.selected .nav-indicator {
background: var(--nav-a-selected-border);
}
.main-nav-link.selected:hover .nav-indicator {
background: var(--nav-a-selected-border-hover);
}
.main-nav-link:hover {
2018-01-13 07:24:05 +00:00
background-color: var(--nav-a-bg-hover);
2018-03-14 14:24:24 +00:00
text-decoration: none;
2018-01-13 07:24:05 +00:00
}
2018-02-16 06:21:23 +00:00
.main-nav-link:hover .nav-link-label {
2018-01-13 07:24:05 +00:00
color: var(--nav-text-color-hover);
}
.main-nav-link:active {
background-color: var(--nav-active-bg);
}
.main-nav-link.selected:active {
background-color: var(--nav-a-selected-active-bg);
}
2018-03-31 00:21:35 +00:00
.nav-link-label {
2018-01-13 07:24:05 +00:00
font-size: 16px;
color: var(--nav-text-color);
padding-left: 10px;
2018-01-23 05:16:27 +00:00
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
2018-01-13 07:24:05 +00:00
}
2018-02-09 02:01:00 +00:00
@media (max-width: 991px) {
2018-02-16 06:21:23 +00:00
.main-nav-link .nav-link-label {
2018-01-13 07:24:05 +00:00
display: none;
}
.nav-icon-and-label {
2018-01-31 06:40:40 +00:00
padding: 20px 0;
2018-01-28 23:53:49 +00:00
}
2018-01-13 07:24:05 +00:00
}
</style>
<script>
import NavItemIcon from './NavItemIcon.html'
2018-02-16 06:21:23 +00:00
import { store } from '../_store/store'
import { on, emit } from '../_utils/eventBus'
import { mark, stop } from '../_utils/marks'
import { doubleRAF } from '../_utils/doubleRAF'
import { scrollToTop } from '../_utils/scrollToTop'
2018-02-16 06:21:23 +00:00
export default {
oncreate () {
let { name } = this.get()
let indicator = this.refs.indicator
on('animateNavPart1', this, ({ fromPage, toPage }) => {
if (fromPage !== name) {
return
}
mark('animateNavPart1 gBCR')
let fromRect = indicator.getBoundingClientRect()
stop('animateNavPart1 gBCR')
emit('animateNavPart2', { fromRect, fromPage, toPage })
})
on('animateNavPart2', this, ({ fromPage, fromRect, toPage }) => {
if (toPage !== name) {
return
}
mark('animateNavPart2 gBCR')
let toRect = indicator.getBoundingClientRect()
stop('animateNavPart2 gBCR')
let translateX = fromRect.left - toRect.left
let scaleX = fromRect.width / toRect.width
indicator.style.transform = `translateX(${translateX}px) scaleX(${scaleX})`
let onTransitionEnd = () => {
indicator.removeEventListener('transitionend', onTransitionEnd)
indicator.classList.remove('animate')
}
indicator.addEventListener('transitionend', onTransitionEnd)
doubleRAF(() => {
indicator.classList.add('animate')
indicator.style.transform = ''
})
})
},
2018-02-16 06:21:23 +00:00
store: () => store,
computed: {
selected: ({ page, name }) => {
return page === name ||
// special case these should both highlight the notifications tab icon
(name === 'notifications' && page === 'notifications/mentions')
},
ariaLabel: ({ selected, name, label, $numberOfNotifications }) => {
2018-02-16 06:58:18 +00:00
let res = label
if (selected) {
2018-02-16 06:58:18 +00:00
res += ' (current page)'
}
2018-02-19 01:28:08 +00:00
if (name === 'notifications' && $numberOfNotifications) {
res += ` (${$numberOfNotifications} notification${$numberOfNotifications === 1 ? '' : 's'})`
2018-02-16 06:58:18 +00:00
}
return res
},
showBadge: ({ name, $hasNotifications }) => name === 'notifications' && $hasNotifications,
badgeNumber: ({ name, $numberOfNotifications }) => name === 'notifications' && $numberOfNotifications
},
methods: {
2018-04-20 04:38:01 +00:00
onClick (e) {
let { selected } = this.get()
if (!selected) {
return
}
if (scrollToTop(/* smooth */ true)) {
e.preventDefault()
e.stopPropagation()
}
}
},
components: {
NavItemIcon
2018-02-16 06:21:23 +00:00
}
}
</script>