content/frontend/default/components/navigation_toggle.vue (80 lines of code) (raw):

<script> import GlButton from '@gitlab/ui/src/components/base/button/button.vue'; const mediaQuery = window.matchMedia(`(max-width: 1199px`); export default { components: { GlButton, }, props: { targetSelector: { type: Array, required: true, }, }, data() { return { width: null, open: null, }; }, created() { this.width = window.innerWidth; mediaQuery.addEventListener('change', this.responsiveToggle); }, beforeDestroy() { mediaQuery.addEventListener('change', this.responsiveToggle); }, methods: { toggle(direction = '') { this.targetSelector.forEach((el) => { const target = document.querySelector(el); if (!target) { return; } switch (direction) { case 'open': target.classList.add('active'); this.open = true; break; case 'close': target.classList.remove('active'); this.open = false; break; default: target.classList.toggle('active'); this.open = !this.open; } }); }, /** * Toggle the menu visibility based on a change event. * * @param {*} e * A media query change event. * In this method, we use the "matches" property to check * if the media query returns true or false. */ responsiveToggle(e) { const newWidth = window.innerWidth; // Browser is less wide than 1199px and has decreased in width. if (e.matches && newWidth < this.width) { this.toggle('close'); } // Browser is wider than 1199px and has increased in width. if (!e.matches && newWidth > this.width) { this.toggle('open'); } this.width = newWidth; }, }, }; </script> <template> <gl-button class="nav-toggle gl-border-none gl-pl-5!" icon="chevron-double-lg-right" @click="toggle" > <span class="label gl-ml-2">Collapse sidebar</span> </gl-button> </template>