UNPKG

vue-stripe-menu

Version:

Creating a navigation menu with animations like on Stripe

390 lines (316 loc) 13 kB
# Vue Stripe Menu <p> <a href="https://circleci.com/gh/Alexeykhr/vue-stripe-menu" rel="nofollow"><img src="https://circleci.com/gh/Alexeykhr/vue-stripe-menu.svg?style=shield" alt="Build Status"></a> <a href="https://codecov.io/github/Alexeykhr/vue-stripe-menu?branch=master"><img src="https://img.shields.io/codecov/c/github/Alexeykhr/vue-stripe-menu/dev.svg" alt="Coverage Status"></a> <a href="https://www.npmjs.com/package/vue-stripe-menu" rel="nofollow"><img src="https://img.shields.io/npm/v/vue-stripe-menu.svg" alt="Version"></a> <a href="https://lgtm.com/projects/g/Alexeykhr/vue-stripe-menu/alerts/" rel="nofollow"><img src="https://img.shields.io/lgtm/alerts/g/Alexeykhr/vue-stripe-menu.svg?logo=lgtm&logoWidth=18" alt="Total alerts"></a> <a href="https://npmcharts.com/compare/vue-stripe-menu?minimal=true"><img src="https://img.shields.io/npm/dm/vue-stripe-menu.svg" alt="Downloads"></a> <a href="https://www.npmjs.com/package/vue-stripe-menu" rel="nofollow"><img src="https://img.shields.io/npm/l/vue-stripe-menu.svg" alt="License"></a> </p> <p align="center"> <img src="https://raw.githubusercontent.com/Alexeykhr/vue-stripe-menu/master/public/img.png?raw=true" alt="Vue Stripe Menu" height="500px"> </p> > Creating a navigation menu with animations like on Stripe **Only for Vue 3** ([changelog](https://github.com/Alexeykhr/vue-stripe-menu/blob/master/CHANGELOG.md#200-2021-04-09)) [Demo Website](https://alexeykhr.github.io/vue-stripe-menu/) [Vue 2 - Branch](https://github.com/Alexeykhr/vue-stripe-menu/tree/vue2) ## How to install Install the library in your project: ```sh $ npm i vue-stripe-menu // or $ yarn add vue-stripe-menu ``` Import components and styles: ```js // >>> Install globally - .js file <<< import { createApp } from 'vue' import VueStripeMenu from 'vue-stripe-menu' createApp({}).use(VueStripeMenu) // >>> Install locally - .vue file <<< import { VsmMenu, VsmMob } from 'vue-stripe-menu' export default { components: { VsmMenu, VsmMob } } ``` Add component: ```vue <template> <vsm-menu :menu="menu"> <template #default="{ item }"> <div style="width: 300px; padding: 30px"> Dropdown content - {{ item.title }} </div> </template> <template #before-nav> <li class="vsm-mob-full"> Left side </li> </template> <template #after-nav> <li class="vsm-mob-hide"> Right side </li> <vsm-mob> <div style="min-height: 200px; padding: 30px"> Mobile Content </div> </vsm-mob> </template> </vsm-menu> </template> <script> export default { data() { return { menu: [ { title: 'Item1', dropdown: 'dropdown-1' }, { title: 'Item2', dropdown: 'dropdown-2' }, { title: 'Just link', attributes: { href: '#clicked' } }, ] } } } </script> ``` Add css/scss styles: ```scss // >>> SCSS style (required sass-loader, node-sass) <<< // https://github.com/Alexeykhr/vue-stripe-menu/blob/master/src/scss/_variables.scss // $vsm-transition: .5s; @import "~vue-stripe-menu/src/scss/index"; // >>> CSS style <<< // @import 'vue-stripe-menu/dist/vue-stripe-menu.css'; .vsm-menu { max-width: 1024px; width: 100%; margin: 0 auto; } .vsm-nav { margin: 0 10px; } .vsm-link-container { display: flex; flex: 1 1 auto; justify-content: center; } @media screen and (max-width: 768px) { .vsm-mob-show { display: block; } .vsm-mob-hide { display: none; } .vsm-mob-full { flex-grow: 1; } } ``` ## Full Example ```vue <template> <vsm-menu :menu="menu" element="header" handler="hover" align="center" :screen-offset="10" :dropdown-offset="0" @open-dropdown="onOpenDropdown" @close-dropdown="onCloseDropdown" > <template #default="{ item }"> <!--Dropdown content of each menu item with a "dropdown" property--> <!--You can replace it with a separate component if each menu item has its own style--> <!--Necessarily need to have at least one element within the slot--> <!--An alternate background will be applied from the 2nd element--> <div style="width: 300px; padding: 30px"> Header: {{ item }} </div> <div style="padding: 30px"> Second element </div> </template> <template #before-nav> <!--Image or svg of website logo--> <li style="width: 50px; height: 50px"> <img src="https://vuejs.org/images/logo.png" alt="My Logo" > </li> </template> <template #title="data"> <!--Display menu items through slots--> {{ data.item.title }} </template> <template #after-nav> <!--Mobile Burger, buttons, etc--> <li class="vsm-mob-hide"> <button>My Button</button> </li> <!--Set "display: block" for the .vsm-mob-show class to display content--> <vsm-mob>Mobile Content</vsm-mob> </template> </vsm-menu> </template> <script> /* eslint-disable */ /* * Inside #after-nav and #before-nav it is recommended to use * to maintain the correct HTML structure: * <li><!--Content--></li> */ export default { data() { return { menu: [ { // display menu item (can be overridden with title slot) title: 'News', // this element now has dropdown content dropdown: 'news', // don't want a button element? Pass HTMLElement or global component // (pass only as a string, component must be globally accessible) element: 'span', // router-link // offset the position of the dropdown menu align: 'center', // menu item can accept all attributes attributes: { // I want more classes! No problem // string, array, object, not matter class: ['my-class1', { 'my-class2': true }], // Custom attributes 'data-big': 'yes' }, // add some events? listeners: { // all possible native events mouseover: (evt) => { console.log('news hover', evt) } }, // just extra properties in the object customAttribute: true, }, { title: 'External Link', attributes: { href: 'https://github.com/Alexeykhr/vue-stripe-menu', target: '_blank' } } // ... ] } }, methods: { onOpenDropdown() { console.log('onOpenDropdown') }, onCloseDropdown() { console.log('onCloseDropdown') } } } </script> ``` ## API ### [Menu] Props | Property | Parameters | Description | Type | Default | Required | | ------------------ | ------------------- | --------------------------------------------------- | -------------- | ------- | -------- | | menu | MenuObject | Description of the menu items | Array | | true | | element | | HTMLElement for the root element | String | header | false | | screen-offset | | Offset from the window screen | String, Number | header | false | | dropdown-offset | | Offset from the dropdown menu | String, Number | header | false | | transition-timeout | | Animation speed in ms (equals $vsm-transition scss) | String, Number | 250 | false | | handler | hover, click | On what event to open dropdown menu | String | hover | false | | align | center, left, right | Offset the position of the dropdown menu | String | center | false | ### [Menu] Events | Name | Description | Return | | -------------- | ------------------------------------------------------ | ----------- | | open-dropdown | Open the dropdown menu, return the active HTMLElement | HTMLElement | | close-dropdown | Close the dropdown menu, return the closed HTMLElement | HTMLElement | ### [Menu] Slots | Name | Parameters | Description | | ---------- | --------------- | --------------------------------------------------- | | default | MenuItem, index | The main content for the dropdown list | | before-nav | before-nav | Content to the left of the list | | after-nav | after-nav | Content to the right of the list | | title | MenuItem, index | Replace the output of menu\[i].title with your own | ### [Menu] Methods `this.$refs[myVsmRef].closeDropdown()` | Name | Parameters | Description | Return | | -------------- | ----------- | ----------------------------------------------------------- | ------ | | toggleDropdown | HTMLElement | Open dropdown menu, if it is an active HTMLElement - close | | | openDropdown | HTMLElement | Open dropdown menu for selected HTMLElement | | | closeDropdown | | Close active dropdown menu | | | resizeDropdown | | Recalculate size and location of dropdown menu | | ### [Menu] Properties `this.$refs[myVsmRef].itemsWithDropdown` | Name | Description | Return | | ---------------------- | ----------------------------------------------- | ------------------------------------------------------------ | | itemsWithDropdown | Filtered menu items with "dropdown" property | Array\<MenuObject> | | elementsWithDropdown | List of HTMLElements that have dropdown content | Array\<MenuObject> | | dropdownContainerItems | List of dropdown HTMLElements | Array<{el: HTMLElement, name: string, content: HTMLElement}> | ### [Menu] MenuObject (menu props) | Property | Type | Description | | ---------- | ------ | ------------------------------------------------------------------------------------------------------- | | title | String | Menu item name. Can also be redefined through the slot | | dropdown | String | Unique value indicates that this item has a dropdown menu | | align | string | Offset the position of the dropdown menu (center/left/right) | | element | String | HTMLElement or global component in the header element, if not specified, it will be <button /> or <a /> | | attributes | Object | All attributes to be assigned in the header element (v-bind) | | listeners | Object | All events to be assigned in the header element (v-on) | ### [Mob] Props | Property | Parameters | Description | Type | Default | Required | | -------- | ---------- | ------------------------------------ | ------- | ------- | -------- | | v-model | | The state of the open/close the menu | Boolean | false | false | ### [Mob] Slots | Name | Parameters | Description | | ---------- | ---------- | ------------------------- | | default | | Main content | | hamburger | | Replace hamburger button | | close | | Replace close button | ### [Mob] Methods `this.$refs[myVsmMobRef].closeDropdown()` | Name | Parameters | Description | Return | | -------------- | ----------- | ------------------- | ------ | | closeDropdown | | Close dropdown menu | | ### Classes | Name | Description | | ------------ | ---------------------------------- | | vsm-mob-show | Show HTMLElements in mobile design | | vsm-mob-hide | Hide HTMLElements in mobile design | ## Contributing ### Install dependencies ```sh $ yarn ``` ### Launch of a demo project (development of lib) ```sh $ yarn dev ``` ### Build a demo project > Don't add build files to PR ```sh $ yarn build ``` ### Build library ```sh $ yarn build:lib ``` ### Run tests ```sh $ yarn test ``` ### Check code on Eslint ```sh $ yarn lint ``` ## Changelog Detailed changes for each release are documented in the [CHANGELOG.md](https://github.com/Alexeykhr/vue-stripe-menu/blob/master/CHANGELOG.md). ## License [MIT](https://opensource.org/licenses/MIT)