Skip to content

Dropdown Component

The Dropdown component is a dropdown component built with Vue 3 and Headless UI. It provides a customizable dropdown interface perfect for displaying navigation items, actions, or other menu options.

Installation

To use the Dropdown component you need to install the @headlessui/vue package.

bash
yarn add @robuust-digital/vue-components @headlessui/vue

Import the component from the dropdown package

js
import { Dropdown } from '@robuust-digital/vue-components/dropdown';

Import CSS

css
@import "@robuust-digital/vue-components/dropdown/css";

Basic Usage

Import and use Dropdown in your Vue components:

vue
<template>
  <Dropdown :items="dropdownItems" label="Options">
    <ButtonBase label="Options"></ButtonBase>
  </Dropdown>
</template>

<script setup>
import { Dropdown, ButtonBase } from '@robuust-digital/vue-components/dialogs';
import {
  AdjustmentsHorizontalIcon,
  ChatBubbleLeftIcon,
  ShieldCheckIcon,
  ArrowLeftStartOnRectangleIcon,
} from '@heroicons/vue/20/solid';

const dropdownItems = [
  {
    href: '#',
    name: 'Account settings',
    icon: AdjustmentsHorizontalIcon,
    as: 'a',
  },
  {
    href: '#',
    name: 'Support',
    icon: ChatBubbleLeftIcon,
    as: 'a',
  },
  {
    href: '#',
    name: 'License',
    icon: ShieldCheckIcon,
    as: 'a',
  },
  {
    href: '#',
    name: 'Sign out',
    icon: ArrowLeftStartOnRectangleIcon,
    as: 'a',
  },
];
</script>

Props

PropTypeDefaultDescription
itemsArrayRequiredArray of items containing name, icon, and other properties for dropdown items
alignLeftBooleanfalseAligns the dropdown menu to the left side of the button when true
fullWidthBooleanfalseSet the width of the dropdown menu to 100% to fix inside the root container
labelString'Options'Label for the default button (when using default button slot)
rootClassString''Additional classes to apply to the root dropdown container

Each item in the items array can have the following properties:

javascript
{
  name: 'Account',          // Required: Display text for the item
  as: 'a',                  // Optional: Component to render ('a', 'button', etc.)
  bindAs: 'RouterLink',     // Optional: Component binding for frameworks
  event: () => {},          // Optional: Custom event handler
  icon: IconComponent,      // Optional: Icon component to display
  
  // Any additional attributes will be passed to the rendered element
  href: '/account',         // Example: For link-based items
  target: '_blank',         // Example: For external links
  rel: 'noopener'          // Example: For external links
}

Slots

Button Slot

The trigger button for the dropdown. You can use the default ButtonBase component or provide your own.

vue
<template>
  <Dropdown :items="dropdownItems">
    <template #button="{ label, button }">
      <Component :is="button" class="custom-button">
        {{ label }}
      </Component>
    </template>
  </Dropdown>
</template>

Items Slot

Customize the rendering of all dropdown items.

vue
<template>
  <Dropdown :items="dropdownItems">
    <template #items="{ items, menuItem }">
      <Component
        :is="menuItem"
        v-for="item in items"
        :key="item.name"
        as="template"
      >
        <div class="custom-item">{{ item.name }}</div>
      </Component>
    </template>
  </Dropdown>
</template>

Item Slot

Customize the rendering of individual dropdown items.

vue
<template>
  <Dropdown :items="dropdownItems">
    <template #item="{ item }">
      <Component
        :is="item.as || 'button'"
        class="custom-item"
        v-bind="item"
      >
        {{ item.name }}
      </Component>
    </template>
  </Dropdown>
</template>

Events

EventArgumentsDescription
dropdown:clickitemEmitted when a dropdown item is clicked

Examples

Default Dropdown with Icons

vue
<template>
  <Dropdown :items="dropdownItems" label="Options">
    <ButtonBase
      label="Options"
      color="light"
      :icon="EllipsisVerticalIcon"
      :icon-left="true"
    />
  </Dropdown>
</template>

Fullwidth Dropdown

vue
<template>
  <Dropdown :items="dropdownItems" :icon="ChevronDownIcon" full-width root-class="w-full" class="w-full" label="Options">
    <ButtonBase
      label="Options"
      color="light"
      :icon="ChevronDownIcon"
      :icon-left="true"
    />
  </Dropdown>
</template>

Custom Button with Left Alignment

vue
<template>
  <Dropdown
    :items="dropdownItems2"
    align-left
    label="Custom Menu"
  >
    <template #button="{ label, button }">
      <Component :is="button" class="custom-button">
        {{ label }}
      </Component>
    </template>
  </Dropdown>
</template>

CSS Customization ⚡️

To customize the dropdown styles global

css
:root {
  /* Available variables */
  --rvc-dropdown-bg-color: var(--rvc-base-input-bg-color);
  --rvc-dropdown-border-radius: var(--rvc-base-border-radius);
  --rvc-dropdown-border-width: var(--rvc-base-border-width);
  --rvc-dropdown-border-color: var(--rvc-base-border-color);
  --rvc-dropdown-icon-size: var(--rvc-base-input-icon-size);
  --rvc-dropdown-icon-color: var(--rvc-base-input-icon-color);
  --rvc-dropdown-icon-color-hover: var(--rvc-base-input-icon-color);
  --rvc-dropdown-item-color: var(--rvc-base-input-color);
  --rvc-dropdown-font-size: var(--rvc-base-font-size);
  --rvc-dropdown-font-weight: var(--rvc-base-font-weight);
  --rvc-dropdown-width: calc(var(--spacing) * 56);
  --rvc-dropdown-padding-x: calc(var(--spacing) * 6);
  --rvc-dropdown-padding-y: calc(var(--spacing) * 6);
  --rvc-dropdown-gap: calc(var(--spacing) * 2);
  --rvc-dropdown-z-index: 50;
  --rvc-dropdown-item-gap: calc(var(--spacing) * 3);
  --rvc-dropdown-item-border-radius: 0;
  --rvc-dropdown-item-bg-color: transparent;
  --rvc-dropdown-item-bg-color-hover: transparent;
  --rvc-dropdown-item-color-hover: var(--color-slate-600);
  --rvc-dropdown-item-padding-x: 0;
  --rvc-dropdown-item-padding-y: 0;
  --rvc-dropdown-item-font-size: var(--rvc-base-font-size);
  --rvc-dropdown-item-font-weight: var(--rvc-base-font-weight);
}