Skip to content

Dropdown

A simple Dropdown component.

Agnostic about its contents; this component only provides a way to toggle open / close its contents: open via click (or Enter when toggle is focused), and close via clickoutside or Escape.

Usage

This component can be imported locally like:

ts
import Dropdown from '@leaflink/stash/components/Dropdown/Dropdown.vue';

In it's current form it manages it's own internal isActive state, allowing the consuming application to control it via it's slots.

Basic usage

By default <Dropdown> will render an ellipse icon button as it's toggle. Nested children will be rendered inside the dropdown itself.

template
<Dropdown>
  <Menu>
    <MenuItem>Item 1</MenuItem>
    <MenuItem>Item 2</MenuItem>
  </Menu>
</Dropdown>

Basic with button text

You can pass a label prop to the <Dropdown> to render a custom label it's toggle.

template
<Dropdown label="Options">
  <Menu>
    <MenuItem>Item 1</MenuItem>
    <MenuItem">Item 2</MenuItem>
  </Menu>
</Dropdown>

Custom toggle

You may use the toggle named slot to render a custom toggle button. It will be passed a toggle method into it's scope.

template
<Dropdown>
  <template #toggle="{ toggle }">
    <button class="button button--primary" @click="toggle">
      Love this <Icon name="heart" />
    </button>
  </template>

  <template #default>
    <Menu>
      <MenuItem>This</MenuItem>
      <MenuItem>That</MenuItem>
      <MenuItem>The other</MenuItem>
    </Menu>
  </template>
</Dropdown>

Custom content

The <Dropdown> component is agnostic about its contents.

template
<Dropdown>
  <img style="display:block" src="https://placekitten.com/200/160" alt="cat" />
</Dropdown>

Keyable items

Any child inside <Dropdown> that has as nested <Menu> with <MenuItems> will become keyboard accessible with the up/down keys.

template
<Dropdown>
  <Menu>
    <MenuItem>Edit</MenuItem>
    <MenuItem>Delete</MenuItem>
  </Menu>
</Dropdown>

Keep open

By default, the <Dropdown> component will close after selecting an item. You can keep it open passing the close-manually prop.

If you want to programatically close the dropdown, you can access the dismiss method exposed either on <Dropdown> by using a template ref with your dropdown instance, or via the default slot.

template
<Dropdown close-manually>
  <template #default="{ dismiss }">
    <div class="tw-p-4 tw-text-ice-700">
      <Button class="tw-mb-2" @click="dismiss()">close</Button>
      <p>Here is some content that will not close the Dropdown when clicked.</p>
      <p>Lorem, ipsum dolor sit amet consectetur adipisicing elit.</p>
      <img
        class="tw-mt-2 tw-block"
        src="https://placekitten.com/200/160"
        alt="cat"
      />
    </div>
  </template>
</Dropdown>

Alignment

By default, <Dropdown> is aligned to the left of the trigger element, but it can be docked to a specific side passing the align property:

Left Aligned

template
<Dropdown>
  <Menu>
    <MenuItem>
      <button>
        Action
      </button>
    </MenuItem>
  </Menu>
</Dropdown>

Right Aligned

template
<Dropdown align="right">
  <Menu>
    <MenuItem>
      <button>
        Action
      </button>
    </MenuItem>
  </Menu>
</Dropdown>

Removing content's max width

You can remove the content's max width passing the fluidContent prop to <Dropdown>.

template
<Dropdown fluid-content>
  <Menu>
    <MenuItem>
      Lorem, ipsum dolor sit amet consectetur adipisicing elit.
    </MenuItem>
    <MenuItem>
      Lorem, ipsum dolor sit amet consectetur adipisicing elit.
    </MenuItem>
  </Menu>
</Dropdown>

Custom offset

You can set a custom offset to <Dropdown>'s content setting the offset prop to an object like { x: number, y: number; }.

template
<Dropdown :offset="{ x: 0, y: 60 }">
  <Menu>
    <MenuItem>Item 1</MenuItem>
    <MenuItem>Item 2</MenuItem>
  </Menu>
</Dropdown>

Mounting container

If you need to mount the <Dropdown> into its parent container, you can pass reattach prop as false, since the default option will mount its contents in the mount point container to circumvent clipping issues from a parent's overflow property.

template
<Dropdown :reattach="false">
  <Menu>
    <MenuItem>Item 1</MenuItem>
    <MenuItem>Item 2</MenuItem>
  </Menu>
</Dropdown>

Styling

If you pass the class property to the <Dropdown>, you will be styling the trigger element of the component. In order to style the dropdown content, you can do it via the contentClass property.

template
<template>
  <Dropdown :class="$style.trigger" :content-class="$style.content">
    <ul class="tw-p-3">
      <li class="tw-p-1.5">Item 1</li>
      <li class="tw-p-1.5">Item 2</li>
    </ul>
  </Dropdown>
</template>

<style module>
  .trigger {
    color: var(--color-red-500);
  }

  .content {
    background: var(--color-orange-100);
  }
</style>

API

See the documentation below for a complete reference to all the props and classes available to the components mentioned here.