advent-of-code

Entries to advent of code, multiple years
git clone git://git.finwo.net/misc/advent-of-code
Log | Files | Refs

nav.vue (3014B)


      1 <template>
      2   <nav :class="isOpen ? 'open' : ''" >
      3     <div class="brand">
      4       <center>
      5         <img src="/assets/logo.png">
      6         <h3>Product</h3>
      7       </center>
      8     </div>
      9     <ul>
     10       <template v-for="route in $router.getRoutes()">
     11         <li v-if="route.meta.nav">
     12           <router-link :to="route.path"><icon>{{ route.meta.icon }}</icon><span>{{ route.name }}</span></router-link>
     13         </li>
     14       </template>
     15     </ul>
     16   </nav>
     17   <div class="topbar">
     18     <div>
     19       <a href="#!" @click.prevent="toggleMenu" v-if="isOpen"><icon>navigate_before</icon></a>
     20       <a href="#!" @click.prevent="toggleMenu" v-if="!isOpen"><icon>menu</icon></a>
     21     </div>
     22     <div class="grow"><h4>{{ $route.name }}</h4></div>
     23   </div>
     24 </template>
     25 
     26 <style scoped>
     27 a {
     28   text-decoration: none;
     29   color: inherit;
     30 }
     31 ul, li {
     32   list-style-type: none;
     33   padding: 0;
     34   margin: 0;
     35 }
     36 svg.feather,
     37 .material-icons,
     38 .material-icons-round {
     39   margin-right: 0.5rem;
     40 }
     41 ul {
     42   margin: 1rem;
     43 }
     44 li a {
     45   border-radius: 0.25rem;
     46   padding: 0.5em;
     47   display: block;
     48 }
     49 li a > * {
     50   vertical-align: middle;
     51 }
     52 li a.router-link-active {
     53   background: #FFF3;
     54 }
     55 li a:hover {
     56   background: #FFF6;
     57 }
     58 nav {
     59   background: var(--col-primary);
     60   color: var(--col-text-icons);
     61   position: fixed;
     62   overflow: auto;
     63   left: -15rem;
     64   top: 0;
     65   height: 100vh;
     66   transition: left 200ms ease;
     67   width: 15rem;
     68 }
     69 nav.open {
     70   left: 0;
     71 }
     72 
     73 .brand img {
     74   width: 50%;
     75   /* border-radius: 50%; */
     76   margin-top: 3rem;
     77 }
     78 
     79 .topbar {
     80   background: #FFF;
     81   display: flex;
     82   padding: 0.5em;
     83   border-bottom: 1px solid #DDD;
     84 }
     85 .topbar .grow {
     86   flex-grow: 1;
     87 }
     88 .topbar .grow * {
     89   margin: 0;
     90 }
     91 </style>
     92 
     93 <style>
     94 body {
     95   position: relative;
     96   transition: margin-left 200ms ease;
     97   margin-left: 0;
     98 }
     99 body.menu-opened {
    100   margin-left: 15rem;
    101 }
    102 </style>
    103 
    104 <script lang="ts">
    105 
    106 import { ref, onMounted, onUnmounted, getCurrentInstance } from 'vue';
    107 import Icon from './icon.vue';
    108 
    109 export default {
    110   components: {Icon},
    111   setup() {
    112     // 1920 / 2 = 960
    113     // Leaving room for window borders, so chose 920
    114     // Allows 2 windows side-by-side in open mode
    115     const initialState = window.innerWidth >= 920;
    116 
    117     // Nicely setup & remove class
    118     // This component IS NOT CLEAN
    119     onMounted(() => {
    120       const bdyClassList = document.body.className.split(' ').filter(n => n && n !== 'menu-opened');
    121       if (initialState) bdyClassList.push('menu-opened');
    122       document.body.className = bdyClassList.join(' ');
    123     });
    124     onUnmounted(() => {
    125       const bdyClassList = document.body.className.split(' ').filter(n => n && n !== 'menu-opened');
    126       document.body.className = bdyClassList.join(' ');
    127     });
    128 
    129     return {
    130       isOpen: ref(initialState),
    131 
    132       toggleMenu() {
    133         this.isOpen = !this.isOpen;
    134         const bdyClassList = document.body.className.split(' ').filter(n => n && n !== 'menu-opened');
    135         if (this.isOpen) bdyClassList.push('menu-opened');
    136         document.body.className = bdyClassList.join(' ');
    137       },
    138 
    139     };
    140   },
    141 
    142 };
    143 </script>