npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@preline/dropdown

v4.2.0

Published

Preline UI is an open-source set of prebuilt UI components based on the utility-first Tailwind CSS framework.

Downloads

26,238

Readme

Dropdown

A dropdown menu displays a list of actions and more with JavaScript dropdown plugin.

npm License: MIT Demo

Contents

Overview

The Dropdown component provides a menu that appears when triggered, displaying a list of actions or options. It supports multiple placement options, customizable triggers, keyboard navigation, and integrates with Floating UI for advanced positioning.

Key Features:

  • Multiple placement options (top, bottom, left, right, auto)
  • Customizable trigger events (click, hover, contextmenu)
  • Floating UI integration for smart positioning
  • Keyboard navigation support (Arrow keys, Home, End, Esc, A-Z)
  • Programmatic control via JavaScript API
  • Event system for lifecycle hooks
  • Accessibility attributes (ARIA) built-in

Installation

To get started, install Dropdown plugin via npm, else you can skip this step if you are already using Preline UI as a package.

npm i @preline/dropdown

CSS

Use @source to register the plugin's JavaScript path for Tailwind CSS scanning, then @import the plugin's CSS files into your Tailwind CSS file.

@import "tailwindcss";

/* @preline/dropdown */
@source "../node_modules/@preline/dropdown/*.js";
@import "./node_modules/@preline/dropdown/variants.css";
@import "./node_modules/@preline/dropdown/theme.css";

JavaScript

Include the JavaScript that powers the interactive elements near the end of your </body> tag:

<script src="./node_modules/@preline/dropdown/index.js"></script>

Manual Initialization

Use the non-auto entry if you need manual initialization. In this mode, automatic initialization on page load is not included, so the component should be initialized explicitly.

<script type="module">
  import HSDropdown from "@preline/dropdown/non-auto.mjs";

  new HSDropdown(document.querySelector("#dropdown"));
</script>

Via Bundler

When using a bundler (Vite, webpack, etc.), import the plugin directly as an ES module.

@preline/dropdown is the auto-init entry: it scans the DOM and initializes matching elements automatically.

import "@preline/dropdown";

@preline/dropdown/non-auto is the manual entry: use it when you want explicit control over when initialization happens, either via autoInit() or by creating a specific instance yourself.

import HSDropdown from "@preline/dropdown/non-auto";

HSDropdown.autoInit();

// Or initialize a specific element manually
const el = document.querySelector("#dropdown");
if (el) new HSDropdown(el);

TypeScript

This package ships with TypeScript type definitions. No additional @types/ package is needed.

Basic usage

The following example demonstrates the minimal HTML structure required for a dropdown component. This is a base template without custom styling - you can apply your own CSS classes and styles as needed. The dropdown menu appears when clicking the button.

<div class="hs-dropdown relative inline-flex">
  <button id="hs-dropdown-unstyled" type="button" class="hs-dropdown-toggle inline-flex justify-center items-center gap-x-2" aria-expanded="false" aria-label="Menu">
    Actions
  </button>

  <div class="hs-dropdown-menu transition-[opacity,margin] duration hs-dropdown-open:opacity-100 opacity-0 w-56 hidden z-10 mt-2 min-w-60 bg-white" role="menu" aria-labelledby="hs-dropdown-unstyled">
    <a class="block" href="#">Newsletter</a>
    <a class="block" href="#">Purchases</a>
    <a class="block" href="#">Downloads</a>
    <a class="block" href="#">Team Account</a>
  </div>
</div>

Structure Requirements:

  • hs-dropdown: Required container wrapper
  • hs-dropdown-toggle: Required button element that triggers the dropdown
  • hs-dropdown-menu: Required container for dropdown menu items
  • Proper ARIA attributes (aria-expanded, aria-label, role="menu", aria-labelledby)

Initial State:

  • Set aria-expanded="false" on the toggle button initially
  • Add hidden class to the dropdown menu initially
  • Menu visibility is controlled by hs-dropdown-open:* modifier classes

Accessibility notes

Keyboard interactions

| Command | Description | | --- | --- | | Enter | Activates the selected menu item. | | ArrowUp / ArrowDown | Focuses previous/next non-disabled item. | | Home / End | Focuses first/last non-disabled item. | | Esc | Closes any open dropdown menus. | | A-Z / a-z | Focuses first item that matches keyboard input. |

Configuration Options

Data Attributes

Data attributes are added directly to HTML elements to configure dropdown behavior.

| Attribute | Target Element | Type | Default | Description | | --- | --- | --- | --- | --- | | data-hs-dropdown-transition | hs-dropdown (container) | - | - | Data attribute to designate the container to be animated. When present, enables transition animations for the dropdown menu. |

CSS Classes (Modifiers)

CSS class modifiers use Tailwind-style syntax with -- prefix to control dropdown behavior.

| Class Modifier | Target Element | Values | Default | Description | | --- | --- | --- | --- | --- | | [--placement:*] | hs-dropdown (container) | "auto" | "auto-start" | "auto-end" | "top" | "top-left" | "top-right" | "bottom" | "bottom-left" | "bottom-right" | "right" | "right-start" | "right-end" | "left" | "left-start" | "left-end" | "bottom" | Specifies the position of the menu when opened relative to the toggle button. | | [--scope:*] | hs-dropdown (container) | "window" | "parent" | "parent" | Determines whether the dropdown will be moved outside the parent, for correct display in elements with hidden overflow. Requires the Floating UI plugin. | | [--auto-close:*] | hs-dropdown (container) | "inside" | "outside" | "false" | "true" | "true" | Specifies the zone, when clicked, which will close the menu. inside closes only when clicking inside, outside closes only when clicking outside, true closes on any click, false prevents auto-close. | | [--has-autofocus:*] | hs-dropdown (container) | "true" | "false" | "true" | Disables autofocus on the first focusable element when opening a dropdown. Set to "false" to disable autofocus. | | [--strategy:*] | hs-dropdown (container) | "fixed" | "absolute" | "fixed" | Sets the position strategy. fixed positions relative to viewport, absolute positions relative to the nearest positioned ancestor. | | [--adaptive:*] | hs-dropdown (container) | "none" | "adaptive" | "adaptive" | Used to disable horizontal position calculations (useful for dropdown menus that span the full width of the screen) while still calculating the vertical position. | | [--gpu-acceleration:*] | hs-dropdown (container) | "true" | "false" | "false" | Disable/enable position calculation using the transform property. Set to "true" to enable GPU acceleration. | | [--offset:*] | hs-dropdown (container) | number | 10 | Sets the dropdown's bottom or top offset in pixels. | | [--flip:*] | hs-dropdown (container) | "true" | "false" | "true" | Flips the menu's placement when it starts to overlap its reference element. Set to "false" to disable flipping. | | [--trigger:*] | hs-dropdown (container) | "hover" | "click" | "contextmenu" | "click" | Event to trigger a dropdown. hover shows on mouse enter, click shows on click, contextmenu shows on right-click. |

Example:

<div class="hs-dropdown --trigger:hover --placement:top --auto-close:false">
  <button class="hs-dropdown-toggle">Hover me</button>
  <div class="hs-dropdown-menu">Menu content</div>
</div>

Required CSS Classes

These classes define the structure and must be present for the dropdown to function.

| Class | Required On | Purpose | | --- | --- | --- | | hs-dropdown | Container wrapper | Groups the toggle and menu elements together | | hs-dropdown-toggle | Button element | The clickable element that activates the dropdown | | hs-dropdown-menu | Menu container | The dropdown menu that appears on trigger |

Optional CSS Classes

| Class | Required On | Purpose | | --- | --- | --- | | hs-dropdown-toggle-wrapper | Wrapper element | A wrapper for a Dropdown toggle, useful when some other element is placed in the Dropdown toggle. For example, if you want to place a "+" button inside an existing Dropdown toggle button that opens a modal. | | hs-dropdown-close | Close element | Dropdown close element (can be multiple). Elements with this class will close the dropdown when clicked. |

Tailwind Modifiers

| Name | Description | | --- | --- | | hs-dropdown-open:* | The modifier that allows you to set Tailwind classes when the dropdown menu is open. |

JavaScript API

The HSDropdown object is available in the global window object after the plugin is loaded.

Instance Methods

These methods are called on a dropdown instance.

| Method | Parameters | Return Type | Description | | --- | --- | --- | --- | | open(target, openedViaKeyboard) | target: VirtualElement \| HTMLElement (optional)openedViaKeyboard: boolean (optional) | boolean | Forces the dropdown menu to open programmatically. Returns true if opened successfully, false otherwise. | | close(isAnimated) | isAnimated: boolean (optional) | boolean | Forces the dropdown menu to close programmatically. isAnimated indicates whether the dropdown menu is closed with animation. Returns true if closed successfully, false otherwise. | | forceClearState() | None | void | Destroys dropdown state without removing the instance. Use to reset dropdown to initial state. | | destroy() | None | void | Destroys the dropdown instance, removes all generated markup, classes, and event listeners. Use when removing dropdown from DOM. |

Static Methods

These methods are called directly on the HSDropdown class.

| Method | Parameters | Return Type | Description | | --- | --- | --- | --- | | HSDropdown.getInstance(target, isInstance) | target: HTMLElement \| string (CSS selector)isInstance: boolean (optional) | HSDropdown \| { id: string \| number, element: HSDropdown } \| null | Returns the dropdown instance associated with the target. If isInstance is true, returns collection item object { id, element } where element is the HSDropdown instance. If isInstance is false or omitted, returns the HSDropdown instance directly. Returns null if dropdown instance is not found. | | HSDropdown.open(target, openedViaKeyboard) | target: HSDropdown \| HTMLElement \| string (CSS selector)openedViaKeyboard: boolean (optional) | void | Opens the dropdown identified by target. Accepts a dropdown instance, DOM element, or CSS selector string. Static alternative to instance open() method. | | HSDropdown.close(target) | target: HSDropdown \| HTMLElement \| string (CSS selector) | void | Closes the dropdown identified by target. Accepts a dropdown instance, DOM element, or CSS selector string. Static alternative to instance close() method. |

Usage Examples

Example 1: Using instance methods (public API)

// Create a new dropdown instance
const dropdown = new HSDropdown(document.querySelector('#hs-dropdown'));
const openBtn = document.querySelector('#hs-open-btn');

// Open dropdown programmatically
openBtn.addEventListener('click', () => {
  dropdown.open();
});

Example 2: Using static methods

const openBtn = document.querySelector('#hs-open-btn');

// Open dropdown using static method (no instance needed)
openBtn.addEventListener('click', () => {
  HSDropdown.open('#hs-dropdown');
});

Example 3: Getting instance and using methods (recommended pattern)

// Get the dropdown instance
const instance = HSDropdown.getInstance('#hs-dropdown', true);

if (instance) {
  const { element } = instance; // element is the HSDropdown instance
  const openBtn = document.querySelector('#hs-open-btn');

  // Use instance methods
  openBtn.addEventListener('click', () => {
    element.open();
  });

  // Clean up when removing from DOM
  function removeDropdown() {
    element.destroy();
  }
}

Example 4: Destroying dropdown instance

const instance = HSDropdown.getInstance('#hs-dropdown', true);

if (instance) {
  const { element } = instance;
  const removeBtn = document.querySelector('#hs-remove-btn');

  removeBtn.addEventListener('click', () => {
    // Clean up before removing from DOM
    element.destroy();
    // Now safe to remove the element
    document.querySelector('#hs-dropdown').remove();
  });
}

Events

Dropdown instances emit events that can be listened to for lifecycle hooks and custom behavior.

| Event Name | When Fired | Callback Parameter | Description | | --- | --- | --- | --- | | on:open | After dropdown menu is opened | HSDropdown (dropdown instance) | Fires after the dropdown menu has been displayed. Use for post-open actions like loading content or tracking analytics. | | on:close | After dropdown menu is closed | HSDropdown (dropdown instance) | Fires after the dropdown menu has been hidden. Use for cleanup or state updates. |

Event Usage Example

// Get dropdown instance
const instance = HSDropdown.getInstance('#hs-dropdown', true);

if (instance) {
  const { element } = instance;

  // Listen to open event
  element.on('open', (dropdownInstance) => {
    console.log('Dropdown opened:', dropdownInstance);
    // Perform actions after dropdown opens
    // e.g., load content, update UI, track analytics
  });

  // Listen to close event
  element.on('close', (dropdownInstance) => {
    console.log('Dropdown closed:', dropdownInstance);
    // Perform cleanup or state updates
  });
}

Common Patterns

Pattern 1: Hover Trigger

Show dropdown on hover instead of click.

<div class="hs-dropdown --trigger:hover">
  <button class="hs-dropdown-toggle">Hover me</button>
  <div class="hs-dropdown-menu">Menu content</div>
</div>

Pattern 2: Programmatic Control

Control dropdown from external buttons.

<div class="hs-dropdown" id="hs-dropdown-first">
  <button class="hs-dropdown-toggle">Actions</button>
  <div class="hs-dropdown-menu">Menu content</div>
</div>

<button id="hs-open-dropdown">Open Dropdown</button>
<button id="hs-close-dropdown">Close Dropdown</button>

<script>
  const instance = HSDropdown.getInstance('#hs-dropdown-first', true);
  
  if (instance) {
    const { element } = instance;

    document.querySelector('#hs-open-dropdown').addEventListener('click', () => {
      element.open();
    });

    document.querySelector('#hs-close-dropdown').addEventListener('click', () => {
      element.close();
    });
  }
</script>

License

Copyright (c) 2026 Preline Labs.

Licensed under the MIT License.