Navigation Menu v1.0
The <e-navigation-menu> component is a component that can be used for .
Usage
An e-navigation-menu has attributes that must be provided,
<e-navigation-menu
:menu=""
:socials=""
:isMobile=""
@toggleEmitNavMenu=""
/>
Attributes
menu | Type: Array | required
socials | Type: Boolean | Default:false
isMobile | Type: Boolean | Default:false
@toggleEmitNavMenu | Type: Function | required
Examples
Below a few interactive examples of e-navigation-menu can be found.
Default
const menu = {
menuItems: [
{
displayText: 'Highlighted Item',
icon: ['star'],
type: 'highlight',
url: 'https://econnect.eu/',
key: '1'
},
{
displayText: 'Standard Item',
icon: ['heart'],
url: 'https://econnect.eu/',
key: '2'
},
{
displayText: 'Dropdown Item',
icon: ['energy'],
key: '3',
menuItems: [
{
displayText: 'First item',
url: 'https://econnect.eu/',
key: '3.1'
},
{
displayText: 'Second item',
url: 'https://econnect.eu/',
key: '3.2'
}
]
}
]
}
<e-navigation-menu
:menu="menu"
@toggleEmitNavMenu=""
/>
:socials='true'
const menu = {
menuItems: [
{
displayText: 'Highlighted Item',
icon: ['star'],
type: 'highlight',
url: 'https://econnect.eu/',
key: '1'
},
{
displayText: 'Standard Item',
icon: ['heart'],
url: 'https://econnect.eu/',
key: '2'
},
{
displayText: 'Dropdown Item',
icon: ['energy'],
key: '3',
menuItems: [
{
displayText: 'First item',
url: 'https://econnect.eu/',
key: '3.1'
},
{
displayText: 'Second item',
url: 'https://econnect.eu/',
key: '3.2'
}
]
}
]
}
<e-navigation-menu
:menu="menu"
:socials="true"
@toggleEmitNavMenu=""
/>
Source Code
e-navigation-menu.vue
<script setup lang="ts">
import { computed, ref } from 'vue';
import { RouteLocation } from 'vue-router';
import { first } from 'lodash-es';
import { EMenuData } from 'types/menu/EMenuData';
import { EMenuItem } from 'types/menu/EMenuItem';
import type { ESocials } from 'types/menu/ESocials';
import ENavigationButton from '../e-navigation-button/e-navigation-button.vue';
import ENavigationFooter from '../e-navigation-footer/e-navigation-footer.vue';
import ENavigationSearchItem from '../e-navigation-search-item/e-navigation-search-item.vue';
export type Props = {
menu: EMenuData;
route: RouteLocation;
socials?: ESocials;
isMobile?: boolean;
};
const props = withDefaults(defineProps<Props>(), {
socials: () => {
return [];
},
isMobile: false
});
const emit = defineEmits<{
(e: 'toggle:nav-menu'): void;
}>();
const navigationMenuClasses = computed(() => {
return {
mobile: props.isMobile
};
});
const openedMenuItemId = ref('');
function toggleSubMenu(menuItem: EMenuItem) {
if (openedMenuItemId.value === menuItem?.key) {
openedMenuItemId.value = '';
} else {
openedMenuItemId.value = menuItem?.key;
}
}
const menuItems = computed(() => {
return props.menu?.menuItems;
});
</script>
<template>
<nav
class="e-navigation-menu"
:class="navigationMenuClasses"
>
<div
class="content"
role="none"
>
<template
v-for="menuItem in menuItems"
:key="menuItem?.key"
>
<e-navigation-search-item
v-if="first(menuItem?.icon) === 'search.svg' && $slots.search"
:menu="menuItem"
>
<template #search>
<slot name="search" />
</template>
</e-navigation-search-item>
<e-navigation-button
v-else
:menu-item="menuItem"
:route="route"
:is-opened="openedMenuItemId === menuItem?.key"
:is-mobile="isMobile"
:active="menuItem?.active"
@toggle="toggleSubMenu(menuItem)"
@toggle:nav-menu="emit('toggle:nav-menu')"
/>
</template>
</div>
<e-navigation-footer
v-if="socials"
:socials="socials"
/>
</nav>
</template>
<style scoped lang="scss">
.e-navigation-menu {
max-width: 300px;
display: flex;
flex-direction: column;
gap: 20px;
margin: 0 auto;
height: 100%;
overflow-x: hidden;
.content {
display: flex;
flex-direction: column;
gap: 20px;
overflow-x: hidden;
min-height: min-content;
}
&.mobile {
min-height: min-content;
overflow-y: auto;
max-width: 100%;
align-items: center;
justify-content: space-between;
flex: 0 1 auto;
height: auto;
.content {
justify-content: center;
max-width: 300px;
}
}
&:not(.mobile) {
.content {
flex: 0 1 auto;
}
}
div:last-child:not(.content) {
margin-top: auto;
}
}
</style>