Skip to content

SelectMenu

Simple, easy-to-use, highly customizable menu solution

GitHub Repo stars GitHub forks

Repository status

CircleCI code coverage npm version license JavaScript Style Guide

Detailed changes for each release are documented in Changelog

If you are using vue 2.x version, please use v-selectmenu 2.x version instead

Installation

Install v-selectmenu component in to your project

sh
npm i v-selectmenu
sh
yarn add v-selectmenu
sh
pnpm add v-selectmenu

Components

v-selectmenu provides the following components

  • SelectMenuDropdown Menu main container
  • SelectMenuTrigger Component built-in trigger button for opening menu
  • SelectMenuBody Menu content main container
  • SelectMenuSection Menu fragment container
  • SelectMenuRow Layout container for horizontal alignment of content
  • SelectMenuColumn Layout container for vertical alignment of content
  • SelectMenuHeader Menu main title bar
  • SelectMenuSubHeader Menu subtitle bar
  • SelectMenuDivider Divider
  • SelectMenuGroup Menu group container
  • SelectMenuGroupItem Menu group item
  • SelectMenuChildLevel Submenu main container
  • SelectMenuSearch Content input module
  • SelectMenuItem Menu item
  • SelectMenuCheckboxGroup Multiple selection container
  • SelectMenuCheckboxItem Multiple selection item
  • SelectMenuRadioGroup Single selection container
  • SelectMenuRadioItem Single selection item

Examples

Basic usage

Set up a menu list and receive commands from menu items uniformly through the action event

Response data for menu item selection events

Event data logs
template
<SelectMenuDropdown>
  <template #trigger>
    <SelectMenuTrigger />
  </template>

  <SelectMenuBody @action="handleAction">
    <SelectMenuItem action="item1">Item 1</SelectMenuItem>
    <SelectMenuItem action="item2">Item 2</SelectMenuItem>
    <SelectMenuItem action="item3">Item 3</SelectMenuItem>
  </SelectMenuBody>
</SelectMenuDropdown>
js
import {
  SelectMenuDropdown,
  SelectMenuTrigger,
  SelectMenuBody,
  SelectMenuHeader,
  SelectMenuItem
} from 'v-selectmenu'

function handleAction (action) {
  console.log(action)
}

No dropdown

Only menu content, no dropdown

Menu without dropdown
Item 1
Item 2
Item 3
template
<SelectMenuBody class="border rounded-4 shadow-sm">
  <SelectMenuHeader>Menu without dropdown</SelectMenuHeader>
  <SelectMenuItem>Item 1</SelectMenuItem>
  <SelectMenuItem>Item 2</SelectMenuItem>
  <SelectMenuItem>Item 3</SelectMenuItem>
</SelectMenuBody>

Menu items can set the front, back and main content of the menu item through slots such as prepend, default and append

Menu item slots
Notifications
23
Helps
Settings
template
<SelectMenuBody>
  <SelectMenuHeader>Menu item slots</SelectMenuHeader>
  <SelectMenuDivider />
  <SelectMenuItem>
    <template #prepend>
      <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bell b-svg-icon" viewBox="0 0 16 16">
        <path d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2M8 1.918l-.797.161A4 4 0 0 0 4 6c0 .628-.134 2.197-.459 3.742-.16.767-.376 1.566-.663 2.258h10.244c-.287-.692-.502-1.49-.663-2.258C12.134 8.197 12 6.628 12 6a4 4 0 0 0-3.203-3.92zM14.22 12c.223.447.481.801.78 1H1c.299-.199.557-.553.78-1C2.68 10.2 3 6.88 3 6c0-2.42 1.72-4.44 4.005-4.901a1 1 0 1 1 1.99 0A5 5 0 0 1 13 6c0 .88.32 4.2 1.22 6"/>
      </svg>
    </template>
    <template #append>
      <span class="badge rounded-pill text-bg-danger">23</span>
    </template>
    Notifications
  </SelectMenuItem>
  <SelectMenuItem>Helps</SelectMenuItem>
  <SelectMenuItem>Settings</SelectMenuItem>
</SelectMenuBody>

This content structure setting also applies to the following components

  • SelectMenuHeader
  • SelectMenuSubHeader
  • SelectMenuRadioItem
  • SelectMenuCheckboxItem

Block Container

The block container SelectMenuSection is used to wrap menu item type components, the height or other styles of the block can be set through custom styles.

In this example, the max-height style is set to manage the height of the block container, so that a scroll bar appears when the block content exceeds the height

template
<SelectMenuBody>
  <SelectMenuSubHeader>Section 1</SelectMenuSubHeader>
  <SelectMenuSection style="max-height: 170px;">
    <SelectMenuItem>Item 1</SelectMenuItem>
    <SelectMenuItem>Item 2</SelectMenuItem>
    <SelectMenuItem>Item 3</SelectMenuItem>
    ...
  </SelectMenuSection>
  <SelectMenuSubHeader>Section 2</SelectMenuSubHeader>
  <SelectMenuSection>
    <SelectMenuItem>Item 1</SelectMenuItem>
    <SelectMenuItem>Item 2</SelectMenuItem>
    <SelectMenuItem>Item 3</SelectMenuItem>
  </SelectMenuSection>
</SelectMenuBody>

Ways to close menu

By default, the dropdown menu will be automatically closed after the menu item is clicked. If you need to keep the menu open, you need to set the hideOnItemClick property to false

template
<SelectMenuBody :hideOnItemClick="false">
  <SelectMenuItem action="item1">Item 1</SelectMenuItem>
  <SelectMenuItem action="item2">Item 2</SelectMenuItem>
  <SelectMenuItem action="item3">Item 3</SelectMenuItem>
</SelectMenuBody>

Divider

Divider component, can be set to horizontal or vertical

template
<SelectMenuBody>
  <SelectMenuHeader>Menu divider</SelectMenuHeader>
  <!-- horizontal divider -->
  <SelectMenuDivider />
  <SelectMenuRow>
    <SelectMenuColumn>
      <SelectMenuItem>Item 1</SelectMenuItem>
      <SelectMenuItem>Item 2</SelectMenuItem>
      <SelectMenuItem>Item 3</SelectMenuItem>
    </SelectMenuColumn>
    <!-- vertical divider -->
    <SelectMenuDivider horizontal={false} />
    <SelectMenuColumn>
      <SelectMenuItem>Item 4</SelectMenuItem>
      <SelectMenuItem>Item 5</SelectMenuItem>
      <SelectMenuItem>Item 6</SelectMenuItem>
    </SelectMenuColumn>
  </SelectMenuRow>
</SelectMenuBody>

The SelectMenuDropdown component of the dropdown menu provides states and operation functions, which can be obtained through scope slot output and the tool function useSelectMenuDropdown provided by the component

ts
interface SelectMenuDropdownUtilities {
  /**
   * Dropdown opening state
   */
  visible?: Ref<boolean>
  /**
   * Dropdown disabled state
   */
  disabled?: Ref<boolean>
  /**
   * Close the dropdown
   */
  closeDropdown?: () => void
  /**
   * Adjust the position of the opened menu
   */
  adjustDropdown?: () => void
}

Scoped slots

The SelectMenuDropdown component outputs data status and operation functions to both the trigger and default slots, making it convenient for users to customize menu content and trigger objects

template
<SelectMenuDropdown>
  <template #trigger={ visible, disabled, closeDropdown, adjustDropdown }>
  ...
  </template>
  <template #default={ visible, disabled, closeDropdown, adjustDropdown }>
    <div>
      <div>Dropdown visible: {{ visible }}</div>
      <div>Dropdown disabled: {{ disabled }}</div>
      <button type="button" @click="closeDropdown">Close</button>
      <button type="button" @click="adjustDropdown">Adjust</button>
    </div>
  </template>
</SelectMenuDropdown>

Utility functions

When the content of the menu is a user-defined component, you can use the useSelectMenuDropdown function to get the menu's state and operation functions

template
<SelectMenuDropdown>
  <template #trigger>
    <SelectMenuTrigger />
  </template>

  <CustomDropdownContent />
</SelectMenuDropdown>
js
import {
  SelectMenuDropdown,
  SelectMenuTrigger
} from 'v-selectmenu'
import CustomDropdownContent from './CustomDropdownContent.vue'
vue
<template>
  <div>
    <div>Dropdown visible: {{ visible }}</div>
    <div>Dropdown disabled: {{ disabled }}</div>
    <button
      type="button"
      @click="closeDropdown"
    >Close dropdown</button>
    <button
      type="button"
      @click="adjustDropdown"
    >Adjust dropdown</button>
  </div>
</template>

<script setup>
import { useSelectMenuDropdown } from 'v-selectmenu'

const {
  visible,
  disabled,
  closeDropdown,
  adjustDropdown
} = useSelectMenuDropdown()
</script>

Built-in trigger button

v-selectmenu has a built-in SelectMenuTrigger component to trigger the opening and closing of the menu. If this button does not meet your needs, you can customize the trigger object through the trigger slot of SelectMenuDropdown

The dropdown layer of v-selectmenu is based on v-dropdown, so the props and events of v-dropdown can be used directly on the SelectMenuDropdown component

Here the trigger property is set to hover, so the drop-down menu is opened by hovering the mouse instead of the default click

template
<SelectMenuDropdown
  trigger="hover"
  @visible-change="visibleChange"
>
  ...
</SelectMenuDropdown>

Props

SelectMenuBody Props

ts
interface MenuBodyProps {
  /**
   * Specifies whether to close the menu after clicking all `SelectMenuItem` in the current menu
   * @default true
   */
  hideOnItemClick?: boolean
}

SelectMenuItem Props

ts
interface MenuItemProps {
  /**
   * The command triggered after the menu item is selected is uniformly received in the action event of `SelectMenuBody`
   */
  action?: string
  /**
   * @default false
   */
  disabled?: boolean
}

SelectMenuDivider Props

ts
interface MenuDividerProps {
  /**
   * Horizontal separator line, set to false to vertical separator line
   * @default true
   */
  horizontal?: boolean
}

Events

SelectMenuBody events

ts
// In response to the menu item selection, get the action value of the item
action: (action: string) => void

Slots

Container type components

  • default menu content

Applicable components

  • SelectMenuBody
  • SelectMenuRow
  • SelectMenuColumn
  • SelectMenuSection
  • prepend front slot
  • default body content slot
  • append tail slot, aligned right

Applicable components

  • SelectMenuItem
  • SelectMenuHeader
  • SelectMenuSubHeader

SelectMenuDropdown slots

  • trigger the trigger element to open the menu
  • default the main content of the menu

SelectMenuTrigger slots

  • default the display text of the component's built-in menu trigger button. If not set, the default display text is Open
  • append The slot at the end of the trigger button. If not set, an arrow icon showing the menu open state is provided by default

Released under the MIT License.