1.0.5 • Published 7 months ago

vue-reactive-sidebar v1.0.5

Weekly downloads
-
License
-
Repository
-
Last release
7 months ago

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>