<template> <div class="container"> <Warning v-if="showWarning" class="warning-container" @enter="(includeQueer) => setConsent(true, includeQueer)" @leave="setConsent(false)" /> <transition name="slide"> <Sidebar v-if="showSidebar" /> </transition> <Header /> <p v-if="config.showDisclaimer" class="disclaimer" v-html="config.disclaimer" /> <p v-if="config.showAnnouncement" class="announcement" v-html="config.announcement" /> <div ref="content" class="content" @scroll="scroll" > <RouterView @scroll="scrollToTop" /> </div> <Filters v-if="showFilters" @close="toggleFilters(false)" /> <Settings v-if="showSettings" @close="toggleSettings(false)" /> </div> </template> <script> import Warning from './warning.vue'; import Header from '../header/header.vue'; import Sidebar from '../sidebar/sidebar.vue'; import Filters from '../filters/filters.vue'; import Settings from '../settings/settings.vue'; function toggleSidebar(state) { this.showSidebar = typeof state === 'boolean' ? state : !this.showSidebar; } function toggleFilters(state) { this.showFilters = state; this.showSidebar = false; } function toggleSettings(state) { this.showSettings = state; this.showSidebar = false; } async function setConsent(consent, includeQueer) { if (consent) { this.showWarning = false; localStorage.setItem('consent', window.env.sessionId); } if (includeQueer) { this.$store.dispatch('setTagFilter', this.$store.state.ui.tagFilter.filter((tag) => !['gay', 'bisexual', 'transsexual'].includes(tag))); return; } this.$store.dispatch('setTagFilter', this.$store.state.ui.tagFilter.concat(['gay', 'bisexual', 'transsexual'])); } function blur(event) { this.events.emit('blur', event); } function resize(event) { this.events.emit('resize', event); } function scroll(event) { this.events.emit('scroll', event); } function scrollToTop() { this.$refs.content.scrollTop = 0; } function trackIframeCampaign() { // no way to capture clicks from an iframe directly if (window.umami && document.activeElement.tagName === 'IFRAME' && document.activeElement.dataset.umamiEvent === 'campaign-click') { window.umami.track('campaign-click', { 'campaign-id': document.activeElement.dataset.umamiEventCampaignId, }); } } function mounted() { document.addEventListener('click', this.blur); window.addEventListener('resize', this.resize); this.events.on('toggleSettings', this.toggleSettings); this.events.on('toggleSidebar', this.toggleSidebar); window.addEventListener('blur', this.trackIframeCampaign); } function beforeUnmount() { document.removeEventListener('click', this.blur); window.removeEventListener('resize', this.resize); window.removeEventListener('blur', this.trackIframeCampaign); } export default { components: { Header, Sidebar, Warning, Filters, Settings, }, data() { return { showSidebar: false, showWarning: localStorage.getItem('consent') !== window.env.sessionId, showFilters: false, showSettings: false, selected: null, }; }, mounted, beforeUnmount, methods: { setConsent, toggleSidebar, toggleFilters, toggleSettings, trackIframeCampaign, blur, resize, scroll, scrollToTop, }, }; </script> <style lang="scss"> .container { position: relative; height: 100%; display: flex; flex-direction: column; overflow: hidden; background: var(--background-soft); color: var(--text); } .content { display: flex; flex-direction: column; flex-grow: 1; overflow-y: auto; overflow-x: hidden; } .content-inner { display: flex; flex-direction: column; flex-grow: 1; overflow-y: auto; overflow-x: hidden; z-index: 1; } .slide-enter-active, .slide-leave-active { &.sidebar-container { transition: background .15s ease-in-out; } .sidebar { transition: transform .15s ease-in-out; } } .slide-enter-from, .slide-leave-to { &.sidebar-container { background: transparent; } .sidebar { transform: translate(100%, 0); } } .column { width: 1200px; max-width: 100%; padding: 0 1rem; margin: 0 auto; box-sizing: border-box; } </style> <style lang="scss" scoped> .disclaimer, .announcement { padding: .5rem 1rem; margin: 0; color: var(--text-light); font-weight: bold; box-shadow: inset 0 0 3px var(--darken-weak); text-align: center; } .disclaimer { background: var(--warn); } .announcement { background: var(--notice); } </style>