vue-reactive-sidebar
v1.0.5
Published
SidebarMenu Vue.js component
Downloads
3
Readme
vue-reactive-sidebar
Ta Vue komponenta doda prilagodljiv stranski meni.
Namestitev
To komponento je mogoče namestiti z uporabo npm:
npm install vue-reactive-sidebar
Uporaba
Uvoz
Za prikaz stranskega menija uvozite komponento v projekt:
import Sidebar from "vue-reactive-sidebar";
// ...
export default {
components: {
Sidebar,
//...
},
// ...
};
in jo nato uporabite v projektu. Primer uporabe:
<template>
<Sidebar :mobile=false :items="exampleMenu" :itemsBottom="exampleMenuBottom">
<template #header>
<img src="./logo.png" alt="Logo" style="max-width: 50%; height: auto;" />
</template>
<template #footer>
<img src="./logout.png" alt="Logout" />
</template>
</Sidebar>
<!-- ... -->
</template>
Prilagajanje
Meni je lahko prikazan na levi strani (za večje zaslone) ali na vrhu (za mobilne telefone in manjše zaslone). Način prikaza menija se nadzoruje z vrednostjo lastnosti mobile. Če je :mobile=false bo meni prikazan na levi, sicer na vrhu (privzeto je :mobile=false).
Elemente, ki bodo v meniju, dodamo z lastnostima items in itemsBottom. Elementi v items bodo prikazani na vrhu, elementi v itemsBottom pa na dnu menija. Njuni vrednosti morata biti Javascript seznama v katerih so elementi, ki bodo prikazani v meniju. Elementi so objekti z lastnostmi:
- label (string): Ime elementa v meniju.
- url (string): Url strani na katero element preusmeri ob kliku. Če element ne preusmerja na drugo stran, naj ta lastnost ne bo nastavljena.
- icon (string): Vsebuje HTML element, ki bo prikazan kot ikona v meniju, zapisan kot string.
- children (list): Seznam enakih objektov, ki so podelementi tega elementa v meniju. Če element nima podelementov, naj ta lastnost ne bo nastavljena.
Primer menija:
export default {
components: {
Sidebar,
//...
},
data() {
return {
exampleMenu: [
{
label: "Item 1",
icon: '<img src="/item.png" alt="Icon" />',
children: [
{
label: "Item 1 Child 1",
url: "",
icon: '<img src="/item.png" alt="Icon" />',
},
{
label: "Item 1 Child 2",
url: "",
icon: '<img src="/item.png" alt="Icon" />',
},
]
},
{
label: "Item 2",
url: "",
icon: '<img src="/item.png" alt="Icon" />',
},
{
label: "Item 3",
url: "",
icon: '<img src="/item.png" alt="Icon" />',
},
],
exampleMenuBottom: [
{
label: "Item 1",
url: "",
icon: '<img src="/item.png" alt="Icon" />',
},
],
// ...
}
},
// ...
};
Prikaz na levi
Za prikaz menija na levi nastavimo :mobile=false. Komponenta lahko zdaj vsebuje še:
- <template #header>: prikazano na vrhu menija,
- <template #footer>: prikazano na dnu menija.
Na dnu menija je gumb, ki zmanjša ali poveča meni. Gumb lahko odstranimo tako, da nastavimo lastnost :minimizable=false.
Prikaz na vrhu
Za prikaz menija na vrhu nastavimo :mobile=true. Komponenta lahko zdaj vsebuje še:
- <template #mobile-left>: prikazano na vrhu menija na levi,
- <template #mobile-header>: prikazano na vrhu menija na sredini,
- <template #mobile-right>: prikazano na vrhu menija na desni,
- <template #mobile-footer>: prikazano na dnu povečanega menija.
Delovanje komponente lahko nadzorujemo z lastnostma:
- sticky (boolean): komponenta se bo premikala skupaj s stranjo,
- mobileClickExit (boolean): ko je meni povečan, ga lahko zapustimo s klikom na ozadje.
Izgled
Izgled lahko spremenimo s spreminjanjem css-ja.
Povozimo lahko naslednje spremenljivke:
:root {
--bg-color: #000000;
--text-color: #ffffff;
--mobile-menu-height: 50px;
--hover-color: #333;
--menu-width: 250px;
--menu-width-collapsed: 50px;
--menu-icon-text-space: 45px;
--menu-padding-vertical: 10px;
--menu-padding-horizontal: 12px;
--menu-padding-horizontal-level: 10px;
--menu-text-size: 16px;
--menu-text-size-level: 2px;
}
Spreminjamo lahko tudi druge css lastnosti elementov, na primer:
.custom-sidebar-item {
background-color: red;
}
Primeri uporabe
Meni na vrhu strani:
<template>
<div>
<Sidebar :mobile=true :items="exampleMenu" :mobileClickExit="false"
:itemsBottom="exampleMenuBottom">
<template #mobile-left>
</template>
<template #mobile-header>
<img src="./logo.png" alt="Logo" />
</template>
<template #mobile-right>
<img src="./logout.png" alt="Logout" />
</template>
<template #mobile-footer>
</template>
</Sidebar>
<main>
VSEBINA STRANI
</main>
</div>
</template>
<script>
import Sidebar from "vue-reactive-sidebar";
export default {
name: "App",
components: { Sidebar },
data() {
return {
exampleMenu: [
{
label: "Item 1",
icon: '<img src="/item.png" alt="Icon" />',
children: [
{
label: "Item 1 Child 1",
url: "",
icon: '<img src="/item.png" alt="Icon" />',
},
{
label: "Item 1 Child 2",
url: "",
icon: '<img src="/item.png" alt="Icon" />',
},
]
},
{
label: "Item 2",
url: "",
icon: '<img src="/item.png" alt="Icon" />',
},
{
label: "Item 3",
url: "",
icon: '<img src="/item.png" alt="Icon" />',
},
],
exampleMenuBottom: [
{
label: "Item 1",
url: "",
icon: '<img src="/itemBelow.png" alt="Icon" />',
},
],
}
},
}
</script>
<style>
:root {
--bg-color: #000000;
--text-color: #ffffff;
--mobile-menu-height: 50px;
--hover-color: #333;
--menu-width: 250px;
--menu-width-collapsed: 50px;
--menu-icon-text-space: 45px;
--menu-padding-vertical: 10px;
--menu-padding-horizontal: 12px;
--menu-padding-horizontal-level: 10px;
--menu-text-size: 16px;
--menu-text-size-level: 2px;
}
</style>
Meni s spremenjenim stilom elementov in avtomatskim prilagajanjem glede na velikost strani:
<template>
<div>
<Sidebar v-if="isDesktopView" :mobile=false :items="exampleMenu"
:itemsBottom="exampleMenuBottom">
<template #header>
<img src="./logo.png" alt="Logo" class="logo" />
<hr class="menu-hr">
<div class="search-container">
<i class="fas fa-search search-icon"></i>
<input type="search" class="menu-search" placeholder="Iskanje">
</div>
</template>
<template #footer>
<div class="circle-container">
<div class="circle">IP</div>
<p class="name-surname">Ime Priimek</p>
<i class="fa-solid fa-sign-out sign-out" />
</div>
</template>
</Sidebar>
<Sidebar v-else :mobile=true :items="exampleMenu" :itemsBottom="exampleMenuBottom">
<template #mobile-left>
</template>
<template #mobile-header>
<img src="./logo.png" alt="Logo" />
</template>
<template #mobile-right>
<i class="fa-solid fa-sign-out" />
</template>
<template #mobile-footer>
</template>
</Sidebar>
<main>
VSEBINA STRANI
</main>
</div>
</template>
<script>
import Sidebar from "vue-reactive-sidebar";
export default {
name: "App",
components: { Sidebar },
data() {
return {
isDesktopView: false,
mobileSize: 600,
exampleMenu: [
{
label: "Item 1",
icon: '<i class="far fa-user" />',
children: [
{
label: "Item 1 Child 1",
url: "",
icon: '<i class="far fa-user" />',
},
{
label: "Item 1 Child 2",
url: "",
icon: '<i class="far fa-user" />',
},
]
},
{
label: "Item 2",
url: "",
icon: '<i class="far fa-user" />',
},
{
label: "Item 3",
url: "",
icon: '<i class="far fa-user" />',
},
],
exampleMenuBottom: [
{
label: "Item 1",
icon: '<i class="far fa-user" />',
children: [
{
label: "Item 1 Child 1",
url: "",
icon: '<i class="far fa-user" />',
},
{
label: "Item 1 Child 2",
url: "",
icon: '<i class="far fa-user" />',
},
]
},
],
}
},
methods: {
updateView() {
this.isDesktopView = window.innerWidth >= this.mobileSize && window.innerHeight >= this.mobileSize;
}
},
mounted() {
this.isDesktopView = window.innerWidth >= this.mobileSize && window.innerHeight >= this.mobileSize;
window.addEventListener("resize", this.updateView);
},
beforeUnmount() {
window.removeEventListener("resize", this.updateView);
}
}
</script>
<style>
.menu-hr {
justify-content: center;
width: 85%;
margin-left: auto;
margin-right: auto;
margin-bottom: 5px;
}
.search-container {
position: relative;
display: inline-block;
}
.search-icon {
position: absolute;
top: 50%;
transform: translateY(-50%);
font-size: 18px;
}
.menu-search {
padding-left: 30px;
width: 200px;
height: 30px;
font-size: 16px;
background-color: var(--bg-color);
border: none;
color: var(--text-color);
}
.menu-search::placeholder {
color: var(--text-color);
}
.menu-search:focus {
outline: none;
}
.circle-container {
display: flex;
align-items: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-top: 10px;
margin-bottom: 10px;
}
.circle {
min-width: 50px;
height: 50px;
border-radius: 50%;
background-color: rgb(91, 91, 180);
color: var(--text-color);
font-size: 24px;
text-align: center;
line-height: 50px;
margin-left: 30px;
}
.name-surname {
position: relative;
top: 8px;
margin-left: 10px;
}
.sign-out {
margin-left: 70px;
transition: margin-left 0.3s ease;
}
:root {
--bg-color: #000000;
--grey-color: #424542;
--text-color: #ffffff;
--mobile-menu-height: 50px;
--hover-color: #222324;
--menu-width: 300px;
--menu-width-collapsed: 50px;
--menu-icon-text-space: 30px;
--menu-padding-vertical: 10px;
--menu-padding-horizontal: 5px;
--menu-padding-horizontal-level: 10px;
--menu-text-size: 16px;
--menu-text-size-level: 2px;
}
.custom-sidebar-item {
justify-content: center;
background-color: var(--grey-color);
margin-top: 15px;
padding: 0;
border-radius: 5px;
height: 50px;
overflow-y: hidden;
}
.custom-items-bottom .custom-sidebar-item {
background-color: transparent;
}
.custom-items-bottom .custom-extended-box {
background-color: var(--bg-color) !important;
}
.custom-items-bottom .custom-submenu {
background-color: var(--bg-color) !important;
}
a:has(.custom-sidebar-item) + div > div > div > a > .custom-sidebar-item {
margin-top: 0;
}
.custom-submenu .custom-sidebar-item {
margin-top: 0px;
}
.custom-dropdown-icon {
transform: translateX(-10px);
}
.custom-link {
display: block;
margin-left: auto;
margin-right: auto;
width: 85% !important;
}
.custom-items.collapsed .custom-link {
width: 92.5% !important;
margin-right: 0;
}
.custom-items-bottom.collapsed .custom-link {
width: 92.5% !important;
margin-right: 0;
}
.custom-submenu {
background-color: var(--grey-color) !important;
border-color: var(--grey-color) !important;
border-radius: 5px;
}
.custom-extended-box {
background-color: var(--grey-color) !important;
border-radius: 5px;
height: 50px;
}
.custom-items.collapsed .custom-link.custom-extended-box {
width: auto !important;
}
.custom-items-bottom.collapsed .custom-link.custom-extended-box {
width: auto !important;
}
.custom-header.collapsed .search-container {
display: none;
}
.custom-header.collapsed .search-container {
display: none;
}
.custom-header .logo {
max-width: 90%;
height: auto;
transition: max-width 0.3s ease;
padding: 5px 5px 0 0;
box-sizing: border-box;
}
.custom-footer.collapsed .circle-container .circle {
display: none;
}
.custom-footer.collapsed .circle-container .name-surname {
display: none;
}
.custom-footer.collapsed .circle-container .sign-out {
margin-left: 10px;
}
.collapsed .circle-container {
padding-left: 5px;
}
</style>