[Custom Vue component] Tail drop-down menu component (2.0) TailDropDown

Article archive: https://www.yuque.com/u27599042/coding_star/kcoem6dgyn8drglb

[Custom Vue Component] DropDown Menu (1.0) DropDownMenu: https://www.yuque.com/u27599042/coding_star/llltv52tchmatwg4

Component effect example

image.png

Constants that components depend on

In the src directory, create the constant directory, create a new tail_drop_down_constant.js file in it, and declare the constants that the component depends on.

/**
 * Constants related to the small tail drop-down menu component
 * @type {*} Constants related to the small tail drop-down menu component
 */

/**
 * The vertical alignment between the drop-down menu and the drop-down link of the small tail drop-down menu component
 * @type {string} The vertical alignment between the drop-down menu and the drop-down link of the small tail drop-down menu component
 */
// align left
export const DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_LEFT = 'left'
// Center it
export const DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_CENTER = 'center'
// right align
export const DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_RIGHT = 'right'

/**
 * The style class name corresponding to the vertical alignment between the drop-down menu and the drop-down link of the small tail drop-down menu component
 * @type {string} The style class name corresponding to the vertical alignment between the drop-down menu and the drop-down link of the small tail drop-down menu component
 */
// align left
export const DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_LEFT = 'tail-drop-down-menu-box-v-align-left'
// Center it
export const DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_CENTER = 'tail-drop-down-menu-box-v-align-center'
// right align
export const DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_RIGHT = 'tail-drop-down-menu-box-v-align-right'
// An array composed of style class names corresponding to the vertical alignment between all drop-down menus and drop-down links
export const dropDownMenuVerticalAlignClasses = [
    DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_LEFT,
    DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_CENTER,
    DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_RIGHT
]

CSS variables that the component depends on

In the src directory, create the styles directory, create the tailComponentsThemeStyles directory in it, create new light.css and dark.css files in the tailComponentsThemeStyles directory, and declare the CSS variables related to theme styles that the components depend on.

/*
 * Bright theme style CSS variables related to the tail component
 */
:root[class*='light'] {<!-- -->
    /*
     * Small tail drop-down menu component style variable
     */
    /* Background color of small tail drop-down menu component */
    --tail-drop-down-bgc: #efefef00;
    /* Background color of menu item of small tail drop-down menu component */
    --tail-drop-down-menu-item-bgc: #efefef99;
    /* Font color of small tail drop-down menu component */
    --tail-drop-down-font-color: #333333;
    /* Mouse hover background color of small tail drop-down menu component */
    --tail-drop-down-hover-bgc: #ccf4ed;
    /* Small tail drop-down menu component mouse hover font color */
    --tail-drop-down-hover-font-color: #1b88e3;
}
/*
 * Dark theme style CSS variables related to the tail component
 */
:root[class*='dark'] {<!-- -->
    /*
     * Small tail drop-down menu component style variable
     */
    /* Background color of small tail drop-down menu component */
    --tail-drop-down-bgc: #454545;
    /* Background color of menu item of small tail drop-down menu component */
    --tail-drop-down-menu-item-bgc: #454545;
    /* Font color of small tail drop-down menu component */
    --tail-drop-down-font-color: #efefef;
    /* Mouse hover background color of small tail drop-down menu component */
    --tail-drop-down-hover-bgc: #565555;
    /* Small tail drop-down menu component mouse hover font color */
    --tail-drop-down-hover-font-color: #00C9A7;
}

Add light or dark class name on html element in index.html file

<html lang="zh-CN" class="light">

Introduce the CSS variables related to theme styles that the component depends on in the main.js file

Configure the src directory alias in the vue project: https://www.yuque.com/u27599042/coding_star/ogu2bhefy1fvahfv

import '@/styles/tailComponentsThemeStyles/light.css'
import '@/styles/tailComponentsThemeStyles/dark.css'

Configure sass preprocessing

https://www.yuque.com/u27599042/coding_star/ua8sgyngldtaa2re

Component source code

In the src/components directory, create the TailDropDown.vue file and write the component in it

<!--
TailDropDown small tail drop-down menu component
-->
<script setup>
import {<!-- -->ref, computed} from 'vue'
import {<!-- -->
  DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_CENTER,
  DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_LEFT,
  DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_RIGHT,
  DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_CENTER,
  DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_LEFT,
  DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_RIGHT
} from "@/constant/tail_drop_down_constant.js";

/**
 * Receive parameters passed by the parent component
 * @type {Prettify<Readonly<ExtractPropTypes<{}>>>>}
 */
const props = defineProps({<!-- -->
  // Whether the small tail drop-down menu component is shrunk and displayed. The shrunken display only displays the drop-down text link icon.
  isShrinkDisplay: {<!-- -->type: Boolean, default: false},
  // Small tail drop-down menu component drop-down text link
  textLink: {<!-- -->type: String, default: 'Small tail drop-down menu drop-down text link'},
  // Small tail drop-down menu component drop-down text link click event handler function
  textLinkClickHandler: {<!-- -->
    type: Function, default: () => {<!-- -->
    }
  },
  // Small tail drop-down menu component drop-down text link height
  textLinkHeight: {<!-- -->type: String, default: '2rem'},
  // Whether to enable drop-down image links to replace drop-down text links
  enableImageLink: {<!-- -->type: Boolean, default: false},
  // Small tail drop-down menu component drop-down image link image address
  imageLinkUrl: {<!-- -->type: String, default: ''},
  // Small tail drop-down menu component drop-down image link image size, the image defaults to a circle centered
  imageSize: {<!-- -->type: String, default: '2rem'},
  // Small tail drop-down menu component drop-down image link click event handler function
  imageLinkClickHandler: {<!-- -->
    type: Function, default: () => {<!-- -->
    }
  },
  //The distance between the drop-down menu of the small tail drop-down menu component and the drop-down link
  menuDistanceWithLink: {<!-- -->type: String, default: '0.5rem'},
  // The vertical alignment between the drop-down menu of the small tail drop-down menu component and the drop-down link, which is left aligned by default
  menuVerticalAlign: {<!-- -->type: String, default: DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_LEFT},
  // Small tail drop-down menu component drop-down menu item, an array composed of {menuItemText: '', menuItemClickHandler: ()=>{}}
  menuItems: {<!-- -->type: Array, default: []},
  //The height of the drop-down menu item of the small tail drop-down menu component
  menuItemHeight: {<!-- -->type: String, default: '2rem'},
})

/**
 * Small tail drop-down menu component drop-down text link style
 * @type {<!-- -->{height: *}}
 */
const textLinkStyle = {<!-- -->
  height: props?.textLinkHeight
}

/**
 * Small tail drop-down menu component drop-down image link style
 * @type {<!-- -->{width: *, height: *}}
 */
const imageLinkStyle = {<!-- -->
  height: props?.imageSize,
  width: props?.imageSize,
}

/**
 * Small tail drop-down menu component drop-down menu item style
 * @type {<!-- -->{height: *}}
 */
const menuItemStyle = {<!-- -->
  height: props?.menuItemHeight
}

/**
 * Control whether the drop-down menu is displayed
 * @type {Ref<UnwrapRef<boolean>>}
 */
const dropDownMenuIsShow = ref(false)

/**
 * Small tail drop-down menu component drop-down menu style
 * @type {<!-- -->{paddingTop: {default: string, type: String | StringConstructor}}}
 */
const menuStyle = {<!-- -->
  paddingTop: props?.menuDistanceWithLink
}

/**
 * Dynamically control the vertical alignment between drop-down menus and drop-down links
 */
//The class name of the drop-down menu
const dropDownMenuClassName = computed(() => {<!-- -->
  // Determine the vertical alignment between the specified drop-down menu and the drop-down link
  switch (props?.menuVerticalAlign) {<!-- -->
    case DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_LEFT:
      return DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_LEFT
    case DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_CENTER:
      return DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_CENTER
    case DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_RIGHT:
      return DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_RIGHT
  }
})

</script>

<template>
  <!-- Small tail drop-down menu component -->
  <div class="tail-drop-down">
    <!-- Small tail drop-down menu component drop-down link -->
    <div
        class="tail-drop-down-link"
        @mouseover="dropDownMenuIsShow = true"
        @mouseout="dropDownMenuIsShow = false"
    >
      <!-- Small tail drop-down menu component drop-down text link -->
      <div
          class="tail-drop-down-text-link"
          v-if="!enableImageLink"
          :style="textLinkStyle"
          @click="textLinkClickHandler"
      >
        <!-- Small tail drop-down menu component drop-down text link icon -->
        <span class="tail-drop-down-text-link-icon">
          <slot name="dropDownTextLinkIcon"></slot>
        </span>
        <span v-show="!isShrinkDisplay">{<!-- -->{ textLink }}</span>
        <!--
          Small tail drop-down menu component drop-down link icon
          When the mouse is hovering over the drop-down menu, the "small tail drop-down menu component drop-down link icon rotation style" is dynamically added when the drop-down menu is displayed.
        -->
        <div
            v-show="menuItems.length > 0"
            class="tail-drop-down-link-icon"
            :class="dropDownMenuIsShow ? 'tail-drop-down-link-icon-rotate' : ''"
        >
          <slot name="dropDownLinkIcon"></slot>
        </div>
      </div>
      <!-- Small tail drop-down menu component drop-down image link -->
      <slot name="dropDownImageLink" v-if="enableImageLink">
        <div
            class="tail-drop-down-image-link"
            :style="imageLinkStyle"
            v-if="enableImageLink"
        >
          <img :src="imageLinkUrl" alt="Small tail drop-down menu drop-down image link">
        </div>
      </slot>
      <!-- Small tail drop-down menu component drop-down menu box -->
      <div
          class="tail-drop-down-menu-box"
          :class="dropDownMenuClassName"
          :style="menuStyle"
      >
        <div
            class="tail-drop-down-menu"
            v-show="dropDownMenuIsShow"
        >
          <slot name="dropDownMenu">
            <ul>
              <!-- Small tail drop-down menu component drop-down menu item -->
              <li
                  class="tail-drop-down-menu-item"
                  v-for="(menuItem, idx) in menuItems"
                  :key="idx"
                  :style="menuItemStyle"
                  @click="menuItem?.menuItemClickHandler"
              >
                <span>{<!-- -->{ menuItem?.menuItemText }}</span>
              </li>
            </ul>
          </slot>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
/*
 * Small tail drop-down menu component
 */
.tail-drop-down {<!-- -->
  color: var(--tail-drop-down-font-color);

  /*
   * Clear default style
   */
  div, ul, li, span {<!-- -->
    margin: 0;
    padding: 0;
    list-style: none;
  }

  /*
   * Small tail drop-down menu component drop-down link
   */
  .tail-drop-down-link {<!-- -->
    position: relative;
    display: inline-block;
    cursor: pointer;
    // Text cannot be selected
    user-select: none;

    /*
     * Small tail drop-down menu component drop-down text link
     */
    .tail-drop-down-text-link {<!-- -->
      box-sizing: border-box;
      padding: 0.5rem;
      border-radius: 0.5rem;
      background-color: var(--tail-drop-down-bgc);
      transition: all 0.3s;
      display: flex;
      justify-content: center;
      align-items: center;
      //The text does not wrap
      white-space: nowrap;

       & amp;:hover {<!-- -->
        background-color: var(--tail-drop-down-hover-bgc);
        color: var(--tail-drop-down-hover-font-color);
      }

      /*
       * Small tail drop-down menu component drop-down link icon
       */
      .tail-drop-down-link-icon {<!-- -->
        width: 100%;
        height: 100%;
        margin-left: 0.5rem;
        transition: all 0.3s;
        //Set the rotation center point x y
        transform-origin: 50% 50%;
        display: flex;
        justify-content: center;
        align-items: end;
      }

      /*
       * Small tail drop-down menu component drop-down link icon rotation style
       */
      .tail-drop-down-link-icon-rotate {<!-- -->
        transform: rotateZ(180deg);
        transition-delay: -0.1s;
      }
    }

    /*
     * Small tail drop-down menu component drop-down picture link
     */
    .tail-drop-down-image-link {<!-- -->
      border-radius: 50%;
      background-color: var(--tail-drop-down-bgc);
      transition: all 0.5s;
      overflow: hidden;

       & amp;:hover {<!-- -->
        transform: rotateZ(360deg);
      }

      img {<!-- -->
        width: 100%;
      }
    }

    /*
     * Small tail drop-down menu component drop-down menu box
     */
    .tail-drop-down-menu-box {<!-- -->
      position: absolute;
      top: 100%;

      /*
       * Small tail drop-down menu component drop-down menu
       */
      .tail-drop-down-menu {<!-- -->
        border-radius: 0.5rem;
        // If overflow hiding will affect the display of the submenu
        // overflow: hidden;

        /*
         * Small tail drop-down menu component drop-down menu item
         */
        .tail-drop-down-menu-item {<!-- -->
          z-index: 1;
          box-sizing: border-box;
          padding: 0.5rem;
          background-color: var(--tail-drop-down-menu-item-bgc);
          transition: all 0.3s;
          overflow: hidden;
          display: flex;
          justify-content: start;
          align-items: center;
          //The text does not wrap
          white-space: nowrap;

           & amp;:hover {<!-- -->
            background-color: var(--tail-drop-down-hover-bgc);
            color: var(--tail-drop-down-hover-font-color);
          }

          //The first child element of the current element's parent element
           & amp;:first-child {<!-- -->
            border-top-right-radius: 0.5rem;
            border-top-left-radius: 0.5rem;
          }

          //The last child element of the current element's parent element
           & amp;:last-child {<!-- -->
            border-bottom-right-radius: 0.5rem;
            border-bottom-left-radius: 0.5rem;
          }
        }
      }
    }

    /*
     * The vertical alignment between the drop-down menu box and the drop-down link of the small tail drop-down menu component
     */
    // align left
    .tail-drop-down-menu-box-v-align-left {<!-- -->
      left: 0;
    }

    // center alignment
    .tail-drop-down-menu-box-v-align-center {<!-- -->
      left: 50%;
      transform: translateX(-50%);
    }

    // right align
    .tail-drop-down-menu-box-v-align-right {<!-- -->
      right: 0;
    }
  }
}
</style>

Component usage instructions

props component properties

Attributes Attribute description Attribute value type Attribute default value
isShrinkDisplay Whether the small tail drop-down menu component is shrunk and displayed. The shrunk display only displays the drop-down link text icon Boolean false
textLink Small tail drop-down menu component drop-down link text String ‘ Small tail drop-down menu drop-down text link’
textLinkClickHandler Small tail drop-down menu component drop-down link text click event handler function Function () => {}
textLinkHeight Small tail drop-down menu component drop-down link text Height String ‘2rem’
enableImageLink Whether to enable the drop-down link image to replace the drop-down link text Boolean false
imageLinkUrl Small tail drop-down menu component drop-down link image image address String
imageSize Small tail drop-down menu component drop-down link image image size, image default Circle Centered String ‘2rem’
imageLinkClickHandler Small tail drop-down menu component drop-down link Image click event handling function Function () => {}
menuDistanceWithLink The distance between the drop-down menu and the drop-down link of the small tail drop-down menu component String ‘0.5rem’
menuVerticalAlign The vertical alignment between the small tail drop-down menu component drop-down menu and the drop-down link, the default left alignment String DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_LEFT
Value reference: https://www.yuque.com/u27599042/coding_star/kcoem6dgyn8drglb#CYUne
menuItems The small tail drop-down menu component drop-down menu item consists of {menuItemText: '', menuItemClickHandler: () =>{}} Array Array []
menuItemHeight Small tail drop-down menu component drop-down menu item height String ‘2rem’

slot slot

< /table>

syntaxbug.com © 2021 All Rights Reserved.
Slot Name Slot Description
dropDownTextLinkIcon The icon before the drop-down link text of the small tail drop-down menu component
dropDownLinkIcon The drop-down link icon of the small tail drop-down menu component (after the drop-down link text icon)
dropDownImageLink Small tail drop-down menu component drop-down link image, you need to make the enableImageLink component property true (use this slot element to replace the drop-down link text)
dropDownMenu Drop-down menu, this slot will replace the default drop-down menu item