<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" ref:indicator></div> </a> <style> .main-nav-link { text-decoration: none; display: flex; justify-content: center; align-items: center; flex: 1; flex-direction: column; } .nav-icon-and-label { padding: 15px 20px; display: flex; justify-content: center; align-items: center; flex: 1; } .main-nav-link.selected { background: var(--nav-a-selected-bg); } .main-nav-link.selected:hover { 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 { background-color: var(--nav-a-bg-hover); text-decoration: none; } .main-nav-link:hover .nav-link-label { 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); } .nav-link-label { font-size: 16px; color: var(--nav-text-color); padding-left: 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } @media (max-width: 991px) { .main-nav-link .nav-link-label { display: none; } .nav-icon-and-label { padding: 20px 0; } } </style> <script> import NavItemIcon from './NavItemIcon.html' 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' export default { oncreate () { const { name } = this.get() const indicator = this.refs.indicator on('animateNavPart1', this, ({ fromPage, toPage }) => { if (fromPage !== name) { return } mark('animateNavPart1 gBCR') const fromRect = indicator.getBoundingClientRect() stop('animateNavPart1 gBCR') emit('animateNavPart2', { fromRect, fromPage, toPage }) }) on('animateNavPart2', this, ({ fromPage, fromRect, toPage }) => { if (toPage !== name) { return } mark('animateNavPart2 gBCR') const toRect = indicator.getBoundingClientRect() stop('animateNavPart2 gBCR') const translateX = fromRect.left - toRect.left const scaleX = fromRect.width / toRect.width indicator.style.transform = `translateX(${translateX}px) scaleX(${scaleX})` const onTransitionEnd = () => { indicator.removeEventListener('transitionend', onTransitionEnd) indicator.classList.remove('animate') } indicator.addEventListener('transitionend', onTransitionEnd) doubleRAF(() => { indicator.classList.add('animate') indicator.style.transform = '' }) }) }, 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 }) => { let res = label if (selected) { res += ' (current page)' } if (name === 'notifications' && $numberOfNotifications) { res += ` (${$numberOfNotifications} notification${$numberOfNotifications === 1 ? '' : 's'})` } return res }, showBadge: ({ name, $hasNotifications }) => name === 'notifications' && $hasNotifications, badgeNumber: ({ name, $numberOfNotifications }) => name === 'notifications' && $numberOfNotifications }, methods: { onClick (e) { const { selected } = this.get() if (!selected) { return } if (scrollToTop(/* smooth */ true)) { e.preventDefault() e.stopPropagation() } } }, components: { NavItemIcon } } </script>