Dropdown (TDropdown)

VueJs dropdown component with configurable classes and infinite variants. Friendly with utility-first frameworks like TailwindCSS.

Playground:


Basic example

<t-dropdown text="Menu">
  <div class="py-1 rounded-md shadow-xs">
    <a
      href="#"
      class="block px-4 py-2 text-sm leading-5 text-gray-700 transition duration-150 ease-in-out hover:bg-gray-100 focus:outline-none focus:bg-gray-100"
      role="menuitem"
    >
      Your Profile
    </a>
    <a
      href="#"
      class="block px-4 py-2 text-sm leading-5 text-gray-700 transition duration-150 ease-in-out hover:bg-gray-100 focus:outline-none focus:bg-gray-100"
      role="menuitem"
    >
      Settings
    </a>
    <a
      href="#"
      class="block px-4 py-2 text-sm leading-5 text-gray-700 transition duration-150 ease-in-out hover:bg-gray-100 focus:outline-none focus:bg-gray-100"
      role="menuitem"
    >
      Sign out
    </a>
  </div>
</t-dropdown>

Props

PropertyTypeDefault valueDescription
textString''Text inside the dropdown button
disabledBooleanundefinedDisables the dropdown button
tagNameString'div'HTML tag that wraps the whole component
dropdownWrapperTagNameString'div'HTML tag that wraps the dropdown (the one that is hidden/shown)
dropdownTagNameString'div'HTML tag that wraps the dropdown content
toggleOnFocusBooleanfalseIf set the modal will be toggled when focus/blur
toggleOnClickBooleantrueIf set the modal will be toggled when click the button
toggleOnHoverBooleanfalseIf set the modal will be toggled when hover the button
hideOnLeaveTimeoutNumber250Timeout to hide the modal after mouseout
showBooleanfalseIf set will show the dropdown (accepts the .sync modifier)
fixedClassesObjectundefinedThe default CSS Fixed classes shared for all variants
classesObject{...} (see below)The default CSS classes
variantsObjectundefinedThe different variants of classes the component have
variant[String, Object]undefinedThe variant that should be used

Classes and variants format

This component expects an object with classes named after every child element.

The properties in that object are the following:

PropertyDescription
buttonDefault button trigger
wrapperWrapper of the whole component
dropdownWrapperWrapper of the dropdown
dropdownWrapper of the dropdown content
enterClassVue Custom Transition Class for the dropdown
enterActiveClassVue Custom Transition Class for the dropdown
enterToClassVue Custom Transition Class for the dropdown
leaveClassVue Custom Transition Class for the dropdown
leaveActiveClassVue Custom Transition Class for the dropdown
leaveToClassVue Custom Transition Class for the dropdown

Default classes

{
  button: 'block px-4 py-2 text-white transition duration-100 ease-in-out bg-blue-500 border border-transparent rounded shadow-sm hover:bg-blue-600 focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none focus:ring-opacity-50 disabled:opacity-50 disabled:cursor-not-allowed',
  wrapper: 'inline-flex flex-col',
  dropdownWrapper: 'relative z-10',
  dropdown: 'origin-top-left absolute left-0 w-56 rounded shadow bg-white mt-1',
  enterClass: 'opacity-0 scale-95',
  enterActiveClass: 'transition transform ease-out duration-100',
  enterToClass: 'opacity-100 scale-100',
  leaveClass: 'opacity-100 scale-100',
  leaveActiveClass: 'transition transform ease-in duration-75',
  leaveToClass: 'opacity-0 scale-95',
}

Scoped slots

SlotDescription
defaultThe dropdown contents goes there
triggerIf used will replace the button trigger
buttonIf used will replace the button content

Default slot

Everything inside the default slot will be inside the dropdown, this slot contains the following data:

SlottypeDescription
hideFunctionIf called it will hide the dropdown
hideIfFocusOutsideFunctionIf called from a focus event (for example in a button inside the dropdown) will hide the dropdown if the focus is outside the component
showFunctionIf called it will show the dropdown
toggleFunctionIf called it will toggle the dropdown
blurHandlerFunctionIntended to be used in any "blureable" element inside the dropdown for better UX

Example:

Consider a dropdown that is used as a menu of items:

<t-dropdown text="Click me">
  <div slot-scope="{ hide, blurHandler }">
    <button
      class="block w-full px-4 py-2 text-sm leading-5 text-gray-700 transition duration-150 ease-in-out hover:bg-gray-100 focus:outline-none focus:bg-gray-100"
      role="menuitem"
      @blur="blurHandler"
    >
      Your Profile
    </button>
    <button
      class="block w-full px-4 py-2 text-sm leading-5 text-gray-700 transition duration-150 ease-in-out hover:bg-gray-100 focus:outline-none focus:bg-gray-100"
      role="menuitem"
      @blur="blurHandler"
    >
      Settings
    </button>

    <button
      class="block w-full px-4 py-2 text-sm leading-5 text-red-500 transition duration-150 ease-in-out border-t hover:bg-gray-100 focus:outline-none focus:bg-gray-100"
      @click="hide"
    >
      Close me
    </button>
  </div>
</t-dropdown>
Is a general recomendation to add the `blurHandler` to any button or blureable element inside the dropdown, that handler ensures to hide the dropdown according to your settings, for example when the user clicks outside.

The example below will be look like this:

Trigger slot

Will replace the current dropdown button, useful for any custom handler.

SlottypeDescription
isShownBooleanIf the dropdown is shown
hideFunctionIf called it will hide the dropdown
hideIfFocusOutsideFunctionIf called from a focus event (for example in a button inside the dropdown) will hide the dropdown if the focus is outside the component
showFunctionIf called it will show the dropdown
toggleFunctionIf called it will toggle the dropdown
blurHandlerFunctionIntended to be used in any "blureable" element that is used a the dropdown trigger
mousedownHandlerFunctionIntended to be used in any "blureable" element that is used a the dropdown trigger
focusHandlerFunctionIntended to be used in any "focuseable" element that is used a the dropdown trigger
keydownHandlerFunctionIntended to be used in any "clickeable" element that is used a the dropdown trigger
disabledBooleanIf the dropdown component is currently disabled

Example:

Rich menu button

<t-dropdown>
  <div
    slot="trigger"
    slot-scope="{
      mousedownHandler,
      focusHandler,
      blurHandler,
      keydownHandler,
      isShown
    }"
  >
    <button
      id="user-menu"
      class="flex items-center pr-3 text-sm text-gray-700 transition duration-150 ease-in-out bg-gray-300 border-2 border-gray-200 rounded-full focus:outline-none focus:shadow-solid"
      :class="{ 'border-gray-300 bg-gray-500 text-white ': isShown }"
      aria-label="User menu"
      aria-haspopup="true"
      @mousedown="mousedownHandler"
      @focus="focusHandler"
      @blur="blurHandler"
      @keydown="keydownHandler"
    >
      <img class="w-8 h-8 mr-2 rounded-full" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="">

      Hi, Alfonso!
    </button>
  </div>

  <div slot-scope="{ hide, blurHandler }">
    <button
      class="block w-full px-4 py-2 text-sm leading-5 text-gray-700 transition duration-150 ease-in-out hover:bg-gray-100 focus:outline-none focus:bg-gray-100"
      role="menuitem"
      @blur="blurHandler"
    >
      Your Profile
    </button>
    <button
      class="block w-full px-4 py-2 text-sm leading-5 text-gray-700 transition duration-150 ease-in-out hover:bg-gray-100 focus:outline-none focus:bg-gray-100"
      role="menuitem"
      @blur="blurHandler"
    >
      Settings
    </button>

    <button
      class="block w-full px-4 py-2 text-sm leading-5 text-red-500 transition duration-150 ease-in-out border-t hover:bg-gray-100 focus:outline-none focus:bg-gray-100"
      @click="hide"
    >
      Close me
    </button>
  </div>
</t-dropdown>
Is a general recomendation to add the `blurHandler`, `mousedownHandler`, `focusHandler` and `keydownHandler` to any button or blureable element that you want to use as a trigger, those handler ensures to toggle the dropdown according to your settings.

The example below will be look like this:

Tooltip

<t-dropdown
  variant="tooltip"
  toggle-on-hover
>
  <span
    slot="trigger"
    class="text-blue-500 border-b border-dashed"
  >
    hey!, hover me
  </span>

  <template>
    Yes you can use the dropdown as tooltip
  </template>
</t-dropdown>

The example below will be look like this:

hey!, hover me
To create the perfect tooltip you can create your own variant and replace the HTML of the different parts to use a `span` for example.

Dropdown group

<t-dropdown>
  <div
    slot="trigger"
    slot-scope="{
      mousedownHandler,
      focusHandler,
      blurHandler,
      keydownHandler,
      isShown
    }"
    class="flex"
  >
    <button
      class="flex items-center justify-center flex-shrink-0 px-3 py-2 text-white bg-blue-500 border-r border-blue-600 rounded-l hover:bg-blue-500"
    >
      Hi, Alfonso!
    </button>
    <button
      class="flex items-center justify-center flex-shrink-0 px-3 py-2 text-white bg-blue-500 border-l border-blue-400 rounded-r hover:bg-blue-500"
      @mousedown="mousedownHandler"
      @focus="focusHandler"
      @blur="blurHandler"
      @keydown="keydownHandler"
    >
      <svg class="w-4 h-4 text-white fill-current" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
        <g stroke="none" stroke-width="1" fill="currentColor" fill-rule="evenodd">
          <g id="icon-shape">
            <polygon id="Combined-Shape" points="9.29289322 12.9497475 10 13.6568542 15.6568542 8 14.2426407 6.58578644 10 10.8284271 5.75735931 6.58578644 4.34314575 8" />
          </g>
        </g>
      </svg>
    </button>
  </div>

  <div slot-scope="{ hide, blurHandler }">
    <button
      class="block w-full px-4 py-2 text-sm leading-5 text-gray-700 transition duration-150 ease-in-out hover:bg-gray-100 focus:outline-none focus:bg-gray-100"
      role="menuitem"
      @blur="blurHandler"
    >
      Your Profile
    </button>
    <button
      class="block w-full px-4 py-2 text-sm leading-5 text-gray-700 transition duration-150 ease-in-out hover:bg-gray-100 focus:outline-none focus:bg-gray-100"
      role="menuitem"
      @blur="blurHandler"
    >
      Settings
    </button>
  </div>
</t-dropdown>

The example below will be look like this:

Notice the in the example above the slot handler are only used in the trigger of the dropdown

Navbar

<t-dropdown
  tag-name="nav"
  :classes="{}"
  :fixed-classes="{}"
  class="bg-blue-800"
>
  <div
    slot="trigger"
    slot-scope="{
      mousedownHandler,
      focusHandler,
      blurHandler,
      keydownHandler,
      isShown
    }"
    class="px-4 mx-auto max-w-7xl sm:px-6 lg:px-8"
  >
    <div class="flex justify-between h-16">
      <div class="flex">
        <div class="flex items-center mr-2 -ml-2 sm:hidden">
          <!-- Mobile menu button -->
          <button
            class="inline-flex items-center justify-center p-2 text-blue-400 transition duration-150 ease-in-out rounded-md hover:text-white hover:bg-blue-700 focus:outline-none focus:bg-blue-700 focus:text-white"
            aria-label="Main menu"
            aria-expanded="false"
            @mousedown="mousedownHandler"
            @blur="blurHandler"
            @keydown="keydownHandler"
          >
            <svg
              :class="{ 'hidden': isShown, 'block': !isShown}"
              class="w-6 h-6"
              fill="none"
              viewBox="0 0 24 24"
              stroke="currentColor"
            >
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
            </svg>
            <svg
              :class="{ 'hidden': !isShown, 'block': isShown}"
              class="w-6 h-6"
              fill="none"
              viewBox="0 0 24 24"
              stroke="currentColor"
            >
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
            </svg>
          </button>
        </div>
        <div class="flex items-center flex-shrink-0 text-white">
          MYAPP
        </div>
        <div class="hidden sm:ml-6 sm:flex sm:items-center">
          <a href="#" class="px-3 py-2 text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-blue-900 rounded-md focus:outline-none focus:text-white focus:bg-blue-700">Users</a>
          <a href="#" class="px-3 py-2 ml-4 text-sm font-medium leading-5 text-blue-300 transition duration-150 ease-in-out rounded-md hover:text-white hover:bg-blue-700 focus:outline-none focus:text-white focus:bg-blue-700">Companies</a>
          <a href="#" class="px-3 py-2 ml-4 text-sm font-medium leading-5 text-blue-300 transition duration-150 ease-in-out rounded-md hover:text-white hover:bg-blue-700 focus:outline-none focus:text-white focus:bg-blue-700">Settings</a>
        </div>
      </div>
    </div>
  </div>

  <div class="sm:hidden">
    <div class="px-2 pt-2 pb-3 sm:px-3">
      <a href="#" class="block px-3 py-2 text-base font-medium text-white transition duration-150 ease-in-out bg-blue-900 rounded-md focus:outline-none focus:text-white focus:bg-blue-700">Users</a>
      <a href="#" class="block px-3 py-2 mt-1 text-base font-medium text-blue-300 transition duration-150 ease-in-out rounded-md hover:text-white hover:bg-blue-700 focus:outline-none focus:text-white focus:bg-blue-700">Companies</a>
      <a href="#" class="block px-3 py-2 mt-1 text-base font-medium text-blue-300 transition duration-150 ease-in-out rounded-md hover:text-white hover:bg-blue-700 focus:outline-none focus:text-white focus:bg-blue-700">Settings</a>
    </div>
  </div>
</t-dropdown>

The example below will be look like this:

Example:

Resize the view

Sign up for our newsletter

Stay up-to-date on news and updates about this project by email.

I will never spam or share your email under any circustance.